aluno: Misael Feitosa Alexandre
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 06/08/2008 (2)
Introdução
O objetivo deste laboratório foi pôr em prática os conceitos básicos de orientação de objetos aprendidos em sala de aula. Para tal, foi proposto um projeto usando a linguagem Java que simula a execução e a entrega de relatórios (de laboratório) por alunos a um professor. A medida que os alunos terminam seus relatórios, estes são colocados numa "Fila de Entrega". O professor corrige os relatórios na ordem em que foram entregues a ele, divulgando a nota.
Desenvolvimento
O projeto foi composto por algumas classes, as quais foram:
Classe Abstrata Aluno
O código da Classe Aluno pode ser visto abaixo:
public abstract class Aluno { public String nome; public int conhecimento; public RelaQueue queue; public double inteligencia, dedicacao; public Aluno(String nome,RelaQueue queue){ this.nome=nome; this.queue=queue; conhecimento=0; } public int getConhecimento(){ return this.conhecimento; } public abstract double getInteligencia(); public abstract double getDedicacao(); public String getNome(){ return nome; } public void fazEEntregaRelatorio(){ double qualidade = (2 * this.getDedicacao() + 1 * this.getInteligencia() ) / 3 ; double originalidade = (1 * this.getDedicacao() + 2 * this.getInteligencia() ) / 3 ; Relatorio rela=new Relatorio(qualidade, originalidade, this); this.queue.queue(rela); conhecimento=conhecimento+1; } }
A Classe Abstrata Aluno contém as principais características (atributos) e ações (métodos) realizáveis por qualquer aluno. Temos quatro atributos públicos:
- nome, do tipo String;
- conhecimento, do tipo inteiro;
- queue, uma instância da classe RelaQueue;
- inteligência e dedicacao, números de ponto flutuante.
No construtor, recebe-se o nome do aluno e um objeto da classe RelaQueue (fila de entrega de relatórios).
Os outros métodos foram:
- getConhecimento, que retornava o valor do conhecimento do aluno;
- getInteligencia e getDedicacao, ambos métodos abstratos;
- getNome, que retornava o nome do aluno;
- fazEEntregaRelatorio, que criava duas variáveis (qualidade e originalidade) que caracterizavam o ralatório, criava uma instância da Classe Relatorio com tais variáveis passadas como parâmetros e adicionava o relatório na fila de entrega. Além disso, o conhecimento do aluno era acrescido.
Nesta classe, além dos conceitos básicos de instânciação de objetos, criação de métodos e atributos, etc, convém salientar o início da aplicação dos conceitos de herança aprendidos, já que a Classe Aluno contém as características básicas para outras classes, ou seja, é uma classe abstrata.
Classe AlunoSafoPreguicoso
O código da Classe AlunoSafoPreguicoso pode ser visto abaixo:
import java.util.*; public class AlunoSafoPreguicoso extends Aluno { public AlunoSafoPreguicoso(String nome, RelaQueue rela) { super(nome, rela); this.inteligencia=1; } private static double generateRandomDe0aMeio() { Random generator = new Random(); double r = generator.nextDouble(); return r * 0.5; } public double getInteligencia(){ return this.inteligencia; } public double getDedicacao(){ this.dedicacao=generateRandomDe0aMeio(); return this.dedicacao; } }
A Classe AlunoSafoPreguicoso tem todas as características da Classe Aluno. As seguintes características foram acrescentas:
- O atributo inteligência de qualquer objeto tem sempre o valor 1 (valor setado no contrutor);
- Criação do método generateRandomDe0aMeio, que retorna um número em ponto flutuante que varia de 0 a 0.5;
- Já que é uma classe que herda de Aluno, deve necessariamente ter os métodos getInteligencia e getDedicacao, que desta vez não são abstratos, e sim implementados. Ambos têm a função de retornar o valor dos atributos aos quais se referem.
Classe AlunoEsforcado
O código da Classe AlunoEsforcado pode ser visto abaixo:
public class AlunoEsforcado extends Aluno { public AlunoEsforcado(String nome, RelaQueue queue) { super(nome, queue); this.inteligencia=0.5; this.dedicacao=1; } public double getInteligencia(){ return this.inteligencia; } public double getDedicacao(){ return this.dedicacao; } }
A Classe AlunoEsforcado tem todas as características da Classe Aluno. As seguintes características foram acrescentas:
- Os atributos inteligencia e dedicacao de qualquer objeto tem sempre o valor 0.5 e 1 (valores setados no contrutor);
- Já que é uma classe que herda de Aluno, deve necessariamente ter os métodos getInteligencia e getDedicacao, que desta vez não são abstratos, e sim implementados. Ambos têm a função de retornar o valor dos atributos aos quais se referem.
Classe RelaQueue
O código da Classe RelaQueue pode ser visto abaixo:
public class RelaQueue { private Relatorio[] array=new Relatorio[10]; private int inicio; private int fim; private Relatorio valor; public RelaQueue() { inicio=0; fim=0; } public void queue(Relatorio elem) { array[fim]=elem; fim=(fim+1)%10; } public Relatorio dequeue(){ valor=array[inicio]; if (fim==inicio){ valor=null; } inicio=(inicio+1)%10; return valor; } }
A Classe RelaQueue representa uma fila de entrega de relatórios. Temos quatro atributos privados:
- array, um array de objetos da Classe Relatorio;
- inicio e fim, do tipo inteiro;
- valor, uma instância da classe Relatorio.
No construtor, nada se recebe. Os atributos início e fim, os quais representam os índices do primeiro e último relatório no array de Relatorios, recebem, ambos, o valor 0.
Dois métodos foram criados:
- queue, o qual acrescenta um relatorio no fim da fila;
- dequeue, o qual retira um relatorio do inicio da fila e o retorna.
Classe Professor
O código da Classe Professor pode ser visto abaixo:
import java.util.*; public class Professor { private RelaQueue queue=new RelaQueue(); public Professor(RelaQueue queue) { this.queue=queue; } private double corrigirRelatorio(Relatorio rela){ double nota = ( rela.getQualidade() + rela.getOriginalidade() + fatorAleatorioDe0a1() ) / 3 * 10; return nota; } private double fatorAleatorioDe0a1(){ Random rand=new Random(); double num=rand.nextDouble(); return num; } public void corrigirRelatorios(){ Relatorio rela=this.queue.dequeue(); while(rela != null) { double nota = corrigirRelatorio(rela); System.out.println(rela.getAluno().getNome()+": "+ nota); rela=this.queue.dequeue(); } } }
No construtor da classe Professor, recebe-se uma fila de relatórios, na qual ele irá operar.
Os métodos da classe Professor foram:
- corrigirRelatorio, método privado que recebe um objeto da classe Relatorio e retorna sua nota (ponto flutuante) através da inspeção dos atributos do relatorio recebido e um cálculo feito com os mesmos;
- fatorAleatorioDe0a1, que retorna um número randômico entre 0 e 1;
- corrigirRelatorios, que percorre toda a fila de relatórios recebida na criação da instancia da classe Professor, corrigindo os relatórios. Para que tal correção seja feita, é feita uma chamada ao método privado corrigirRelatorio para cada relatório corrigido. É também impresso na tela o nome do dono e a nota de cada relatório.
Classe Relatorio
O código da Classe Relatorio pode ser visto abaixo:
public class Relatorio { private double qualidade; private double originalidade; private Aluno aluno; public Relatorio(double qualidade, double originalidade, Aluno aluno) { this.qualidade=qualidade; this.originalidade=originalidade; this.aluno=aluno; } public double getQualidade() { return this.qualidade; } public double getOriginalidade() { return this.originalidade; } public Aluno getAluno() { return this.aluno; } }
Os atributos da Classe Relatorio são:
- qualidade e originalidade, atributos privados em formato de número em ponto flutuante que representam, respectivamente, a qualidade e a originalidade do relatório;
- aluno, objeto da Classe Aluno.
No construtor da classe Relatorio, recebe-se a qualidade e a originalidade do mesmo (ambos atribuídos aos respectivos atributos) e o objeto (que pode ser tanto da classe AlunoEsforcado ou da Classe AlunoSafoPreguicoso) que vai ser atribuído ao atributo aluno.
Os métodos da classe Relatorio são:
- getQualidade, que retorna o valor da qualidade do relatório;
- getOriginalidade, que retorna o valor da originalidade do relatório;
- getAluno, que retorna o objeto (classes AlunoEsforcado ou AlunoSafoPreguicoso) recebido na criação do relatório.
O diagrama das classes já compiladas no BlueJ pode ser visto abaixo:
Figura 1 - Diagrama das Classes já compiladas.
A seguir, foi feitos um conjunto de testes.
Testes
No conjunto de teste, a primeira parte consistiu na criação das instâncias:
- queue, instância da classe RelaQueue;
- prof, instância da classe Professor, que recebe queue como lista de relatórios a se corrigir;
- aluno1 e aluno2, instâncias da classe AlunoEsforcado, ambas recebendo queue como a lista de relatórios para a qual devem entregar seus relatórios, e com os nomes "John Smith" e "Mark Smith", respectivamente;
- aluno3 e aluno4, instâncias da classe AlunoSafoPreguicoso, ambas recebendo queue como a lista de relatórios para a qual devem entregar seus relatórios, e com os nomes "Joseph Smith" e "Robert Smith", respectivamente;
A entrada na linha de código do Cod Pad do BlueJ pode ser vista abaixo:
A segunda parte foi constituída de um conjunto de testes para verificar:
- Se, para o aluno1, instância de AlunoEsforcado, o atributo inteligencia estava entre 0.01 e 0.5 e o atributo dedicacao estava entre 0.01 e 1;
- Se, para o aluno3, instância de AlunoSafoPreguicoso, o atributo inteligencia estava entre 0.01 e 1, se o atributo dedicacao era realmente randômico e menor que 0.5.
A entrada na linha de código do Cod Pad do BlueJ pode ser vista abaixo:
Na terceira parte, inicialmente, fez-se que aluno1 entregasse seu relatório através da chamada de seu método público fazEEntregaRelatorio. Em seguida, retira-se este relatório (colocado na instância rela1) da fila de relatórios (através do método dequeue do objeto queue já criado). Após tal preparação, é feito um conjunto de teste para verificar:
- Se o dono de rela1 é realmente aluno1 (é feito através de uma comparação de aluno1 com o retorno do método getAluno de rela1);
- Se o nome de quem entregou o relatório (aluno1) é realmente "John Smith";
- Se a qualidade de rela1 é menor que 0.9;
- Se a qualidade de rela1 é maior que 0.8;
- Se a originalidade de rela1 é menor que 0.7;
- Se a originalidade de rela1 é maior que 0.6.
A entrada na linha de código do Cod Pad do BlueJ pode ser vista abaixo:
Na quarta e última parte, inicialmente, faz-se que os outros alunos também entreguem seus relatórios (através da chamada de seu método público fazEEntregaRelatorio). Em seguida, faz-se que a instância da classe Professor prof corrija todos os relatórios na fila e imprima as notas. Deve-se notar que se espera que sejam impressos somente os resultados de aluno2, aluno3 e aluno4, já que o relatório de aluno1 foi retirado da fila para inspeção.
A entrada na linha de código do Cod Pad do BlueJ pode ser vista abaixo:
Classe de Testes
Foi então criada um classe de testes para que todos os testes feitos manualmente acima pudessem ser feitos todos de uma vez.
Abaixo, pode-se ver o conteúdo da classe Teste:
public class Teste extends junit.framework.TestCase { public void testAluno(){ //criando os objetos RelaQueue queue = new RelaQueue(); Professor prof = new Professor(queue); AlunoEsforcado aluno1 = new AlunoEsforcado("John Smith", queue); AlunoEsforcado aluno2 = new AlunoEsforcado("Mark Smith", queue); AlunoSafoPreguicoso aluno3 = new AlunoSafoPreguicoso("Joseph Smith", queue); AlunoSafoPreguicoso aluno4 = new AlunoSafoPreguicoso("Robert Smith", queue); //teste de alunoesforcado assertEquals(0.5, aluno1.getInteligencia(), 0.01); assertEquals(1, aluno1.getDedicacao(), 0.01); //teste de alunosafo assertEquals(1.0, aluno3.getInteligencia(), 0.01); assertTrue(aluno3.getDedicacao() != aluno3.getDedicacao()); //deve ser randomica assertTrue(aluno3.getDedicacao() < 0.5); //alunos comecam a fazer os relas aluno1.fazEEntregaRelatorio(); //roubamos o relatório do primeiro aluno para investigá-lo Relatorio rela1 = queue.dequeue(); assertEquals(aluno1, rela1.getAluno()); assertTrue(rela1.getAluno().getNome().equals("John Smith")); assertTrue(rela1.getQualidade() < 0.9); assertTrue(rela1.getQualidade() > 0.8); assertTrue(rela1.getOriginalidade() < 0.7); assertTrue(rela1.getOriginalidade() > 0.6); //os outros continuam a fazer os relas aluno2.fazEEntregaRelatorio(); aluno3.fazEEntregaRelatorio(); aluno4.fazEEntregaRelatorio(); //deve exibir a coreção dos relas dos aluno2, aluno3, e aluno4, nesta ordem //pois "roubamos" o relatório do aluno1 prof.corrigirRelatorios(); } }
Ao se fazer um TestAll na classe, o resultado obtido foi:
O código fonte das 6 classes criadas pode ser acessado pelos links abaixo:
Aluno
AlunoEsforcado
AlunoSafoPreguicoso
Professor
RelaQueue
Relatorio
Conclusão
Este primeiro laboratório foi importante para a fixação dos conceitos básicos de orientação a objetos dados em aula. Dentre estes, podemos citar o uso de classes, métodos, herança e instâncias, conceitos estes não existente em linguagens procedurais como C. A execução da atividade foi relativamente tranquila, visto que eu já tinha os conceitos básicos tanto de orientação a objetos como de comandos em linguagem Java. A utilidade do que foi aprendido é muito ampla, já que conceitos como classes e heranças são usados praticamente todas as vezes que se programa em uma linguagem orientada o objetos.
A meu ver, apesar de parecer uma atividade relativamente difícil para um primeiro contato de quem nunca viu linguagens orientadas a objeto ou Java, o laboratório cumpre a função de fixar os conceitos básicos.
Seu código ficou Ok. Só não entendi muito bem porque você definiu as variáveis de Aluno como públicas. Além disto, inteligência e dedicacao não deveriam ser definidos em Aluno, e sim em AlunoSafoPreguicoso e AlunoEsforcado. É responsabilidade da subclasse definir como quer calcular estes valores, e pode não fazer sentido ter uma variável de instância com eles (como no caso de dedicacao randomico). Você colocou em Aluno porque já sabia de antemão como as subclasses funcionariam (ou seja, acoplou a classe às subclasses).
Seu rela ficou um pouco carregado demais (e muitas vezes o que você fez foi descrever o que estava escrito no código). Dá para perceber que você compreendeu o código, mas teoricamente isto seria verdade pelo fato de tê-lo escrito. Você poderia ter se concentrado menos nisto e canalizado seus esforços em analisar o que foi feito, mostrar e discutir os conceitos de OO, explicar o porque de você ter feito isto ou aquilo (ex. definir as variáveis como públicas) e até mesmo a criticar/sugerir mudanças no código original. Para um exemplo de um bom rela veja o do Melegati.