aluno: Rafael Siqueira
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 21/08/2008 (4)
Introdução
Nesse segundo laboratório, o objetivo era dar um upgrade no laboratório passado através da inclusão de uma classe Simulador que possibilita maior interação com o usuário uma vez que não exige conhecimentos de programação para que o programa seja rodado. A classe recebe inputs do usuário via linhas de comando e assim coordena-se a interação entre os objetos. Em seguida, mais alterações foram feitas no programa para deixá-lo mais completo e mais 'real'. As mudanças nas classes e na relação entre elas foi repassada para o Simulador para que o propósito do mesmo pudesse ser alcançado com as atualizações feitas.
Desenvolvimento
A estrutura do programa é muito similar à do laboratório anterior, tendo como principais alterações as seguintes:
1) Classe Aluno deixa de ser abstrata, tendo como subclasses alunos de universidades diferentes
2) Criação da classe abstrata Comportamento
3) Utilização de exceções para limitar o comportamento dos alunos dependendo de sua universidade
4) Criação de uma fila de genéricos, da qual RelaQueue é subclasse
5) Classe Simulador
As únicas classes inalteradas foram as Professor e Relatório, cujos códigos já seguem abaixo.
Professor
import java.util.*; //Importa biblioteca de Java para que se utilize alguma de suas classes pré-definidas public class Professor { //Variáveis internas RelaQueue queue; //Contrutor public Professor(RelaQueue queue) { this.queue=queue; } //Corrige um relatorio e retorna a nota do aluno no mesmo private double corrigirRelatorio(Relatorio rela) { double nota =(rela.getOriginalidade()+rela.getQualidade()+fatorAleatorioDe0a1())/3*10; return nota; } //Retorna um número aleatório de 0 a 1 public double fatorAleatorioDe0a1() { Random generator = new Random(); double r = generator.nextDouble(); return r * 1; } //Método que faz com que todos os relatórios sejam tirados da fila, sejam corrigidos e tenham suas notas impressas na tela public void corrigirRelatorios() { Relatorio rela = queue.dequeue(); while (rela!=null) { System.out.println(rela.getAluno().getNome()+": "+corrigirRelatorio(rela)); rela=queue.dequeue(); } } }
Relatório
public class Relatorio { //Variáveis internas private double qualidade; private double originalidade; private Aluno aluno; //Construtor public Relatorio(double qualidade,double originalidade,Aluno aluno) { this.qualidade = qualidade; this.originalidade = originalidade; this.aluno = aluno; } //Getter de qualidade public double getQualidade() { return this.qualidade; } //Getter de originalidade public double getOriginalidade() { return this.originalidade; } //Getter de aluno public Aluno getAluno() { return this.aluno; } }
Classe Aluno
A classe aluno foi alterada de forma a não ter como subclasses classes determinadas pelo comportamento do aluno. Agora, a classe aluno possui uma variável comportamento que é definida pela criação de uma classe Comportamento que será explicada a seguir. As subclasses de aluno agora são referentes às diferentes universidades que cada aluno pode estudar: ITA, USP e Unicamp. Cada uma possui restrições quanto ao comportamento que o aluno pode ter. Segue abaixo o código da classe Aluno e de suas subclasses: AlunoITA, AlunoUSP e AlunoUnicamp.
Aluno
public class Aluno { //Variáveis internas private int conhecimento = 0; private String nome = new String(); private RelaQueue queue; Comportamento comportamento; //Construtor public Aluno(String nome,RelaQueue queue) { this.nome=nome; this.queue=queue; this.comportamento = new Esforcado(this); } //Método que faz o relatório do aluno dependendo das características do seu comportamento e o coloca na pilha de relatórios public void fazEEntregaRelatorio() { double qualidade = (2 * this.comportamento.getDedicacao() + 1 * this.comportamento.getInteligencia() ) / 3 ; double originalidade = (1 * this.comportamento.getDedicacao() + 2 * this.comportamento.getInteligencia() ) / 3 ; Relatorio rela = new Relatorio (qualidade,originalidade,this); queue.queue(rela); conhecimento++; } //Getter de nome public String getNome() { return this.nome; } //Getter de conhecimento public double getConhecimento() { return this.conhecimento; } //Getter de dedicacao public double getDedicacao() { return this.comportamento.getDedicacao(); } //Getter de inteligencia public double getInteligencia() { return this.comportamento.getInteligencia(); } //Setter de comportamento public void setComportamento(Comportamento comportamento) throws Exception { this.comportamento=comportamento; } }
AlunoITA
public class AlunoITA extends Aluno { //Construtor public AlunoITA(String nome,RelaQueue queue) { super(nome,queue); } //Tratamento das restrições de comportamento que o aluno do ITA deve ter, ele não pode ser burro, através do uso de exceções public void setComportamento(Comportamento comportamento) throws Exception { if(comportamento instanceof Burro) throw new Exception(); super.setComportamento(comportamento); } }
AlunoUSP
public class AlunoUSP extends Aluno { //Construtor public AlunoUSP(String nome,RelaQueue queue) { super(nome,queue); } //Tratamento das restrições de comportamento que o aluno da USP deve ter, ele não pode ser summa nem safo&preguicoso, através do uso de exceções public void setComportamento(Comportamento comportamento) throws Exception { if(comportamento instanceof SafoPreguicoso || comportamento instanceof Summa) throw new Exception(); super.setComportamento(comportamento); } }
AlunoUnicamp
public class AlunoUnicamp extends Aluno { //Construtor public AlunoUnicamp(String nome,RelaQueue queue) { super(nome,queue); } //Tratamento das restrições de comportamento que o aluno da Unicamp deve ter, ele não pode ser summa nem safo&preguicoso, através do uso de exceções public void setComportamento(Comportamento comportamento) throws Exception { if(comportamento instanceof SafoPreguicoso || comportamento instanceof Summa) throw new Exception(); super.setComportamento(comportamento); } }
Criação da classe Comportamento
A classe Comportamento é uma classe abstrata que possui 6 subclasses: Summa, SafoPreguicoso, Esforcado, Imprevisivel, Pemba e Burro. Essas subclasses possuem diferentes maneiras de determinar a inteligência e a dedicação do Aluno que possui tal comportamento. E ainda, há na classe Aluno um método setter de comportamento para que possa haver mudança do comportamento do aluno. Segue abaixo o código da classe Comportamento e de cada uma das suas subclasses.
Comportamento
public abstract class Comportamento { //Variáveis internas public Aluno aluno; //Construtor public Comportamento(Aluno aluno) { this.aluno = aluno; } //Métodos abstratos subscritos nas suas subclasses abstract double getDedicacao(); abstract double getInteligencia(); }
Summa
public class Summa extends Comportamento { //Variáveis internas private double inteligencia = 1; private double dedicacao = 1; //Construtor public Summa(Aluno aluno) { super(aluno); } //Getter de inteligencia public double getInteligencia() { return this.inteligencia; } //Getter de dedicacao public double getDedicacao() { return this.dedicacao; } }
SafoPreguicoso
import java.util.*; //Importa biblioteca de Java para utilização de alguma de suas classes pré-definidas public class SafoPreguicoso extends Comportamento { //Variáveis internas private double inteligencia = 1; private double dedicacao; //Construtor public SafoPreguicoso(Aluno aluno) { super(aluno); } //Getter de inteligencia public double getInteligencia() { return this.inteligencia; } //Getter de dedicacao public double getDedicacao() { Random generator = new Random(); double r = generator.nextDouble(); return r * 0.5; } }
Esforcado
public class Esforcado extends Comportamento { //Variáveis internas private double inteligencia = 0.5; private double dedicacao = 1; //Construtor public Esforcado(Aluno aluno) { super(aluno); } //Getter de inteligencia public double getInteligencia() { return this.inteligencia; } //Getter de dedicacao public double getDedicacao() { return this.dedicacao; } }
Imprevisivel
import java.util.*; //Importa biblioteca de Java para utilização de alguma de suas classes pré-definidas public class Imprevisivel extends Comportamento { //Variáveis internas private double inteligencia; private double dedicacao; //Construtor public Imprevisivel(Aluno aluno) { super(aluno); } //Getter de inteligencia public double getInteligencia() { Random generator = new Random(); double r = generator.nextDouble(); return r * 1; } //Getter de dedicacao public double getDedicacao() { Random generator = new Random(); double r = generator.nextDouble(); return r * 1; } }
Pemba
import java.util.*; //Importa biblioteca de Java para utilização de alguma de suas classes pré-definidas public class Pemba extends Comportamento { //Variáveis internas private double inteligencia; private double dedicacao; //Construtor public Pemba(Aluno aluno) { super(aluno); } //Getter de inteligencia public double getInteligencia() { Random generator = new Random(); double r = generator.nextDouble(); return r * 0.5; } //Getter de dedicacao public double getDedicacao() { Random generator = new Random(); double r = generator.nextDouble(); return r * 0.5; } }
Burro
public class Burro extends Comportamento { //Variáveis internas private double inteligencia = 0; private double dedicacao = 0; //Construtor public Burro(Aluno aluno) { super(aluno); } //Getter de inteligencia public double getInteligencia() { return this.inteligencia; } //Getter de dedicacao public double getDedicacao() { return this.dedicacao; } }
Implementando restrições utilizando exceções
Cada subclasse de aluno representa um estudante que estuda em uma das três universidades: ITA, Unicamp e USP. No programa, dependendo de onde o aluno estuda, ele tem restrições no tipo de comportamento que pode possuir:
- Alunos do ITA não podem ter o comportamento Burro
- Alunos da USP e da Unicamp não podem ter o comportamento Summa nem SafoPreguicoso
Diante disso, fizemos um tratamento dessas restrições através do uso de exceções do Java. Ele funciona basicamente da seguinte forma: quando um método de uma classe lança uma exceção, essa deve ser tratada toda vez que o método for chamado; e assim nós podemos, quando alguém tentar fazer algo que não é possível ser feito, 'capturar' essa exceção e fazermos de outra forma, exibindo mensagens de erro e afins. Assim, o método setComportamento() dos alunos lança uma exceção que é tratada no método main() da classe Simulador, quando o usuário escolhe o comportamento do aluno depois de ter escolhido sua universidade. Segue abaixo um excerto do código da classe Simulador na qual mostramos o tratamento de uma exceção, quando o usuário tenta setar o comportamento de burro à um AlunoITA.
try { aluno[i].setComportamento(new Burro(aluno[i])); } catch(Exception e) { c.printf("Alunos do ITA nao podem ser burros!\n"); c.printf("Digite um comportamento válido"); exc=1; }
Criação de uma fila de genéricos
Tal criação se deu de maneiro complicada devido à disperidade de opiniões e maneiras propostas para sua implementação, nem todas que funcionaram. De qualquer forma, a idéia foi não restringir a fila a apenas os relátorios dos alunos, qualquer coisa pode ser armazenada nela. O formato e as funcionalidades são os mesmos do laboratório passado. A classe RelaQueue, portanto, nesse laboratório, é uma subclasse dessa fila de genéricos e herda todos os métodos da superclasse, não tendo nenhum método próprio. Seguem abaixo os códigos das duas classes, nos quais evidencia-se como foi feita essa transição (uso do tipo Object[]) da generalidade para a particularidade do problema (Relatórios na fila).
Queue<T>
import java.util.Vector; //Importa uma biblioteca de Java da qual faz parte o tipo Object[] usado no código public class Queue<T> { //Estado inicial - fila vazia private Object[] array = new Object[10]; private int inicio = 0; private int fim = 0; //Comportamento //Método que coloca algo na fila public void queue (T obj) { array[fim]=obj; fim = (fim+1) % 10; } //Método que retorna algo tirando-o da fila, retornando nulo caso a mesma esteja vazia public T dequeue() { if (inicio==fim) { return null; } else { T objsaida = (T) array[inicio]; inicio = (inicio+1) % 10; return objsaida; } } }
RelaQueue
public class RelaQueue extends Queue<Relatorio> { }
Classe Simulador
Como já explicado, a classe simulador garante uma interação muito facilitada entre o programa e o usuário, de forma que esse último não preciso ter conhecimento de programação para poder usar o programa. Abaixo, seguem as duas classes Simulador, a primeira se refere ao primeiro laboratório e a segunda ao segundo, depois que foram feitas todas as alterações aqui descritas.
Simulador 1
import java.io.Console; //Biblioteca de java que foi usada nesse laboratório para receber entradas do usuário via teclado e escrever na tela, através dos métodos readLine() e printf() respectivamente public class Simulador { public static void main(String[] args) { //Definição de um console para que se possa usar os métodos readLine() e printf() Console c = System.console(); int num, i, comp; //Criação dos alunos do { c.printf("\n"); String num2 = c.readLine("Quantos alunos deseja criar? "); num = Integer.parseInt(num2); if (num<=0) c.printf("Digite um número válido"); } while (num<=0); Aluno[] aluno = new Aluno[num]; //Criação da fila de relatórios RelaQueue queue = new RelaQueue(); //Definição do nome e do comportamento dos mesmos for (i=0;i<num;i++) { String nome = c.readLine("Digite o nome do aluno "+(i+1)); c.printf("Qual o comportamento do aluno "+nome); c.printf("?\n"); c.printf("1 - Safo & Preguicoso\n"); c.printf("2 - Esforcado\n"); do { c.printf("\n"); String comp2 = c.readLine("Digite o comportamento "); comp = Integer.parseInt(comp2); if(comp>2 || comp<1) c.printf("Digite um comportamento válido"); } while (comp>2 || comp<1); if(comp==1) aluno[i] = new AlunoSafoPreguicoso(nome,queue); else aluno[i] = new AlunoEsforcado(nome,queue); } //Criação do professor Professor professor = new Professor(queue); //Alunos fazem e entregam seus relatórios for (i=0;i<num;i++) { aluno[i].fazEEntregaRelatorio(); } c.printf("\nOs alunos fizeram e entregaram seus relatórios"); c.printf("\nO professor corrigiu os relatórios, as notas seguem abaixo:\n\n"); //Professor corrige os relatórios e imprime suas notas professor.corrigirRelatorios(); } }
Simulador 2
import java.io.Console; //Biblioteca de java que foi usada nesse laboratório para receber entradas do usuário via teclado e escrever na tela, através dos métodos readLine() e printf() respectivamente public class Simulador { public static void main(String[] args) { //Definição de um console para que se possa usar os métodos readLine() e printf() Console c = System.console(); int num, i, comp, uni, exc; //Criação dos alunos do { c.printf("\n"); String num2 = c.readLine("Quantos alunos deseja criar? "); num = Integer.parseInt(num2); if (num<=0) c.printf("Digite um número válido"); } while (num<=0); Aluno[] aluno = new Aluno[num]; //Criação da fila de relatórios RelaQueue queue = new RelaQueue(); //Definição do nome, da universidade e do comportamento dos alunos for (i=0;i<num;i++) { String nome = c.readLine("Digite o nome do aluno "+(i+1)); c.printf("Qual a universidade do aluno "+nome); c.printf("?\n"); c.printf("1 - ITA\n"); c.printf("2 - USP\n"); c.printf("3 - Unicamp\n"); do { c.printf("\n"); String uni2 = c.readLine("Digite a universidade "); uni = Integer.parseInt(uni2); if(uni>3 || uni<1) c.printf("Digite uma universidade válida"); } while (uni>3 || uni<1); if(uni==1) aluno[i] = new AlunoITA(nome,queue); else if (uni==2) aluno[i] = new AlunoUSP(nome,queue); else aluno[i] = new AlunoUnicamp(nome,queue); c.printf("Qual o comportamento do aluno "+nome); c.printf("?\n"); c.printf("1 - Safo & Preguicoso\n"); c.printf("2 - Esforcado\n"); c.printf("3 - Summa\n"); c.printf("4 - Imprevisivel\n"); c.printf("5 - Pemba\n"); c.printf("6 - Burro\n"); //Tratamento das exceções para os comportamentos dos alunos dependendo de sua universidade do { exc=0; c.printf("\n"); String comp2 = c.readLine("Digite o comportamento "); comp = Integer.parseInt(comp2); if(comp==1) { if (uni!=1) { //Alunos da USP ou da Unicamp não podem ser safos e preguiçosos try { aluno[i].setComportamento(new SafoPreguicoso(aluno[i])); } catch(Exception e) { c.printf("Alunos que nao sao do ITA nao podem ser safos e preguicosos!\n"); c.printf("Digite um comportamento válido"); exc=1; } } } else if(comp==2) { try { aluno[i].setComportamento(new Esforcado(aluno[i])); } catch(Exception e) { } } else if(comp==3) { if (uni!=1) { //Alunos da USP ou da Unicamp não podem ser summa try { aluno[i].setComportamento(new SafoPreguicoso(aluno[i])); } catch(Exception e) { c.printf("Alunos que nao sao do ITA nao podem ser summa!\n"); c.printf("Digite um comportamento válido"); exc=1; } } } else if(comp==4) { try { aluno[i].setComportamento(new Imprevisivel(aluno[i])); } catch(Exception e) { } } else if(comp==5) { try { aluno[i].setComportamento(new Pemba(aluno[i])); } catch(Exception e) { } } else if (comp==6) { if(uni==1) { //Alunos do ITA não podem ser burros try { aluno[i].setComportamento(new Burro(aluno[i])); } catch(Exception e) { c.printf("Alunos do ITA nao podem ser burros!\n"); c.printf("Digite um comportamento válido"); exc=1; } } } if(comp>6 || comp<1) c.printf("Digite um comportamento válido"); } while ((comp>6 || comp<1) || exc==1); } //Criação do professor Professor professor = new Professor(queue); //Alunos fazem e entregam seus relatórios for (i=0;i<num;i++) { aluno[i].fazEEntregaRelatorio(); } c.printf("\nOs alunos fizeram e entregaram seus relatórios"); c.printf("\nO professor corrigiu os relatórios, as notas seguem abaixo:\n\n"); //Professor corrige os relatórios e imprime suas notas professor.corrigirRelatorios(); } }
Seguem abaixo imagens que comprovam o bom funcionamento do programa.
Imagem 1 - Novo diagrama de classes do Laboratório 1
Imagem 2 - Diagrama de classes do Laboratório 2
Imagem 3 - Resultado dos testes realizados pela classes Teste fornecida para os alunos
O programa foi rodado no 'cmd' do Windows (DOS) através do comando 'java Simulador' dentro da pasta de cada laboratório
Imagem 4 - Resultado da execução do programa do Laboratório 1
Imagem 5 - Resultado da execução do programa do Laboratório 2
Conclusão
O laboratório foi muito interessante pois foi feita uma ligação com o primeiro laboratório através da melhoria de várias de suas funcionalidadess, bem como com diversas maneiras de torná-lo mais complexo. Achei importante a implementação de uma fila genérica que comporta o enfileiramente de qualquer coisa. Tal tipo de implementação é essencial para códigos complexos bem como para a manipulação de mudanças de código, evitando que muito do código tenha que ser alterado em decorrência de uma ligeira mudança nas exigências da aplicação que se cria. O tratamento de exceções foi outra coisa que não tinha idéia da existência e que ampliou os horizontes da minha programação em Java. Em suma, o laboratório foi bem proposto e estruturado apenas senti que mais suporte podia ter sido dado no tocante à execução do programa, execução da classe Simulador. Não ficou claro o que se queria exatamente. A utilização do 'cmd' aprendi com um colega e vi que outros partiram para um lado ainda inexplorado na matéria, a criação de uma interface gráfica mais complexa para o programa, não sei como eles fizeram isso.
corrigido. Vamos ver uma aula sobre interface gráfica, mas só dá para passar uma idéia de como funciona. Mas, basicamente, é aprender a usar a API Swing, que faz interfaces gráficas em Java.