Lab2 Misael Alexandre

aluno: Misael Feitosa Alexandre
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 07/09/2008 (6)

Introdução

Este laboratório consistiu em uma modificação do primeiro laboratório de forma a torná-lo mais abrangente e flexível ao inserir novos conceitos de Orientação a Objetos e interação com o usuário. Dentre os conceitos novos aplicados, pode-se citar o tratamento de excessões (Exceptions) e o uso de genéricos.

Desenvolvimento

Inicialmente foram feitas modificações na forma de tratamento do comportamento do aluno. Tais modificações visaram tornar o comportamento mais flexível para, dentre outras coisas, suportar mudanças.

Foi então criada uma classe abstrata Comportamento, a qual estava ligada diretamente a um aluno. Tal classe teve então os métodos abstratos getInteligencia() e getDedicacao().

Classe Comportamento

public abstract class Comportamento
{
    private Aluno aluno;
 
    //Construtor que recebe o Aluno "dono" do comportamento
    public Comportamento(Aluno aluno){
        this.aluno=aluno;
    }
 
    //Métodos abstratos a serem escritos nas subclasses
    public abstract double getInteligencia();
    public abstract double getDedicacao();
}

A partir da classe abstrata Comportamento (geral), foram criadas subclasses específicas que continham os comportamentos específicos. Além dos comportamentos Esforcado e SafoPreguicoso, foram criados os comportamentos Imprevisivel, Burro, Pemba e Summa. Todas estas subclasses concretas tratavam a inteligencia e dedicacao do aluno de acordo com suas características e implementavam os métodos getInteligencia() e getDedicacao().

O códigos das classes pode ser visto abaixo:

Classe Esforcado

public class Esforcado extends Comportamento 
{
    public double inteligencia, dedicacao;
    public Esforcado(Aluno aluno)
    {
        super(aluno);
        this.inteligencia=0.5;
        this.dedicacao=1;
    }
 
    public double getInteligencia(){
        return this.inteligencia;
    }
 
    public double getDedicacao(){
        return this.dedicacao;
    }
}

Classe SafoPreguicoso

import java.util.*;
 
public class SafoPreguicoso extends Comportamento 
{
    public double inteligencia, dedicacao;
    public SafoPreguicoso(Aluno aluno)
    {
        super(aluno);
        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;
    }
 
}

Classe Burro

public class Burro extends Comportamento 
{
    public double inteligencia, dedicacao;
    public Burro(Aluno aluno)
    {
        super(aluno);
        this.inteligencia=0;
        this.dedicacao=0;
    }
 
    public double getInteligencia(){
        return this.inteligencia;
    }
 
    public double getDedicacao(){
        return this.dedicacao;
    }
}

Classe Pemba

import java.util.*;
 
public class Pemba extends Comportamento 
{
    public double inteligencia, dedicacao;
    public Pemba(Aluno aluno)
    {
        super(aluno);
    }
 
    private static double generateRandomDe0aMeio()
    {
        Random generator = new Random();
        double r = generator.nextDouble();
        return r * 0.5;
    }
 
    public double getInteligencia(){
        this.inteligencia=generateRandomDe0aMeio();
        return this.inteligencia;
    }
 
    public double getDedicacao(){
        this.dedicacao=generateRandomDe0aMeio();
        return this.dedicacao;
    }
 
}

Classe Imprevisivel

import java.util.*;
 
public class Imprevisivel extends Comportamento 
{
    public double inteligencia, dedicacao;
    public Imprevisivel(Aluno aluno)
    {
        super(aluno);
    }
 
    private static double generateRandomDe0aUm()
    {
        Random generator = new Random();
        double r = generator.nextDouble();
        return r * 1;
    }
 
    public double getInteligencia(){
        this.inteligencia=generateRandomDe0aUm();
        return this.inteligencia;
    }
 
    public double getDedicacao(){
        this.dedicacao=generateRandomDe0aUm();
        return this.dedicacao;
    }
 
}

Classe Summa

public class Summa extends Comportamento 
{
    public double inteligencia, dedicacao;
    public Summa(Aluno aluno)
    {
        super(aluno);
        this.inteligencia=1;
        this.dedicacao=1;
    }
 
    public double getInteligencia(){
        return this.inteligencia;
    }
 
    public double getDedicacao(){
        return this.dedicacao;
    }
}

Feito tal, modificou-se então a classe Aluno. Tal classe virou concreta e, para implementar os comportamentos, foi criada uma variável interna comportamento que determina o comportamento atual do aluno, ou seja, pode haver mudanças. Foram criados também os métodos getInteligencia() e getDedicacao(), que delegavam seu valor à variável comportamento. Convém salientar que o comportamento inicial de um aluno criado é Esforcado (criado no construtor).

Classe Aluno

public class Aluno
{
    public String nome;
    public int conhecimento;
    public RelaQueue queue;
    public Comportamento comportamento;
 
    //Cria novo aluno com comportamento inicial Esforcado
    public Aluno(String nome,RelaQueue queue){
        this.nome=nome;
        this.queue=queue;
        conhecimento=0;
        this.comportamento=new Esforcado(this);
    }
 
    public int getConhecimento(){
        return this.conhecimento;
    }
 
    //Delega getConhecimento e getInteligencia à variável comportamento
    public double getInteligencia(){
        return this.comportamento.getInteligencia();    
    }
 
    public double getDedicacao(){
        return comportamento.getDedicacao();
    }
 
    //Seta um novo comportamento com tratamento de Exceptions
    public void setComportamento(Comportamento comportamento) throws Exception{
        this.comportamento=comportamento;
    }
 
    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;
    }
 
}

Para que um aluno possa ter uma universidade, foram criadas subclasses de Aluno chamadas AlunoITA, AlunoUnicamp e AlunoUSP. Entretanto, foram implementadas restrições de forma que os alunos do ITA nunca podem ser Burros, e os alunos da USP e Unicamp nunca serão nem Summas nem SafosPreguicosos. Para que tais restrições fossem implementadas, foi usado tratamento de Exceptions.

Os códigos das classes AlunoITA, AlunoUnicamp e AlunoUSP podem ser vistos abaixo.

Classe AlunoITA

public class AlunoITA extends Aluno
{
    //Construtor igual ao da classe Aluno
    public AlunoITA(String nome,RelaQueue queue)
    {
        super(nome,queue);
    }
 
    //Seta o comportamento lançando uma Exception se ele for instancia
    //da Classe Burro.
    public void setComportamento(Comportamento comportamento) throws Exception{
        if (comportamento instanceof Burro){
            throw new Exception();
        }
        super.setComportamento(comportamento);
    }
 
}

Classe AlunoUSP

public class AlunoUSP extends Aluno
{
 
    //Construtor igual ao da classe Aluno
    public AlunoUSP(String nome,RelaQueue queue)
    {
        super(nome,queue);
    }
 
    //Seta o comportamento lançando uma Exception se ele for instancia
    //da Classe Summa ou da Classe SafoPreguicoso.
    public void setComportamento(Comportamento comportamento) throws Exception{
        if (comportamento instanceof Summa || comportamento instanceof SafoPreguicoso) throw new Exception();
        super.setComportamento(comportamento);
    }
 
}

Classe AlunoUnicamp

public class AlunoUnicamp extends Aluno
{
 
    //Construtor igual ao da classe Aluno
    public AlunoUnicamp(String nome,RelaQueue queue)
    {
        super(nome,queue);
    }
 
    //Seta o comportamento lançando uma Exception se ele for instancia
    //da Classe Summa ou da Classe SafoPreguicoso.
    public void setComportamento(Comportamento comportamento) throws Exception{
        if (comportamento instanceof Summa || comportamento instanceof SafoPreguicoso) throw new Exception();
        super.setComportamento(comportamento);
    }
 
}

Foi então criada uma Classe chamada Simulador, que tinha um método main e visava interação com o usuário, de forma que o usuário pudesse criar quantos alunos quisesse, indicando, para cada um, sua universidade e seu comportamento. Se tais comportamentos não fossem possíveis dada certa universidade, era lançada uma Exception como já mostrado acima.

Classe Simulator

import java.util.Scanner;
 
public class Simulator
{
 
   public static void main(String args[])
   {
       //Criado variáveis iniciais
       Aluno[] vetor_aluno=new Aluno[50];
       String universidade, comportamento;
       RelaQueue queue=new RelaQueue();
       int num;
 
       //Criado um scanner de teclado
       Scanner scan = new Scanner (System.in);
       scan.useDelimiter("\n");
 
       //Entra-se com o numero de alunos
       System.out.println("Entre com o número de alunos");
       String numero=scan.next();
       num=Integer.parseInt(numero);
 
       //Para cada um dos alunos...
       for (int i=0;i<num;i=i+1)
       {
 
           //Entra-se com o nome do aluno
           System.out.println("Entre com o nome do aluno "+(i+1)+": ");
           String nome=scan.next();
 
           //Entra-se com a universidade do aluno
           do{
               System.out.println("Entre com a universidade do aluno "+(i+1)+" (ITA, USP ou Unicamp): ");
               universidade=scan.next();
           } while (!universidade.equals("ITA")&&!universidade.equals("USP")&&!universidade.equals("Unicamp"));
           if (universidade.equals("ITA")){
               vetor_aluno[i]=new AlunoITA(nome, queue);
           }
           else if (universidade.equals("Unicamp")){
               vetor_aluno[i]=new AlunoUnicamp(nome, queue);
           }
           else{
               vetor_aluno[i]=new AlunoUSP(nome, queue);
           }
 
           //Entra-se com o comportamento do aluno
           do{
               System.out.println("Entre com o comportamento do aluno "+(i+1)+" (Imprevisivel,Burro,Pemba,SafoPreguicoso,Summa,Esforcado): ");
               comportamento=scan.next();
           } while (!comportamento.equals("SafoPreguicoso")&&!comportamento.equals("Burro")&&!comportamento.equals("Pemba")&&!comportamento.equals("Imprevisivel")&&!comportamento.equals("Summa")&&!comportamento.equals("Esforcado"));
 
           //Dado o comportamento, tenta-se setar o mesmo para o aluno. Não
           //havendo possibilidade, trata-se a Exception
 
           if (comportamento.equals("Esforcado")){
               Esforcado comp=new Esforcado(vetor_aluno[i]);
               try{
                  vetor_aluno[i].setComportamento(comp);
               }
               catch(Exception e){
                   System.out.println("Voce tentou fazer algo impossivel");
               }
           }
 
           else if (comportamento.equals("Burro")){
               Burro comp=new Burro(vetor_aluno[i]);
               try{
                  vetor_aluno[i].setComportamento(comp);
               }
               catch(Exception e){
                   System.out.println("Voce tentou fazer algo impossivel");
               }
           }
           else if (comportamento.equals("Imprevisivel")){
               Imprevisivel comp=new Imprevisivel(vetor_aluno[i]);
               try{
                  vetor_aluno[i].setComportamento(comp);
               }
               catch(Exception e){
                   System.out.println("Voce tentou fazer algo impossivel");
               }
           }
           else if (comportamento.equals("Summa")){
               Summa comp=new Summa(vetor_aluno[i]);
               try{
                  vetor_aluno[i].setComportamento(comp);
               }
               catch(Exception e){
                   System.out.println("Voce tentou fazer algo impossivel");
               }
           }
           else if (comportamento.equals("SafoPreguicoso")){
               SafoPreguicoso comp=new SafoPreguicoso(vetor_aluno[i]);
               try{
                  vetor_aluno[i].setComportamento(comp);
               }
               catch(Exception e){
                   System.out.println("Voce tentou fazer algo impossivel");
               }
           }
           else{
               Pemba comp=new Pemba(vetor_aluno[i]);
               try{
                  vetor_aluno[i].setComportamento(comp);
               }
               catch(Exception e){
                   System.out.println("Voce tentou fazer algo impossivel");
               }
           }
 
       }
 
       //Faz e entrega o relatorio de todos os alunos
       for (int i=0;i<num;i=i+1)
       {
           vetor_aluno[i].fazEEntregaRelatorio();
       }
 
    }  
 
}

Por fim, implementando o uso de genéricos, foram feitas modificações na Classe RelaQueue. Foi inicialmente criado uma Queue genérica, que não necessariamente era feita de objetos da Classe Relatorio, chamada Queue<T>. A Classe RelaQueue passou então a ser subclasse de Queue<Relatorio> (definindo que T neste caso era Relatorio). Os códigos de Queue<T> e RelaQueue podem ser vistos abaixo.

Classe Queue<T>

public class Queue<T>
{
    //Cria array de objetos genéricos
    private Object[] array=new Object[50];
    private int inicio=0;
    private int fim=0;
    private T valor;
 
    //coloca um objeto na pilha
    public void queue(T elem)
    {
        array[fim]=elem;
        fim=(fim+1)%10;
    }
 
    //retira um objeto da pilha
    public T dequeue(){
        valor=(T)array[inicio];
        if (fim==inicio){
            valor=null;
        }
        inicio=(inicio+1)%10;
        return valor;
    }
}

Classe RelaQueue

//Herda de Queue<Relatorio> (faz T igual a Relatorio)
public class RelaQueue extends Queue<Relatorio>{
}

As outras Classes continuaram da mesma maneira do primeiro laboratório.

TESTES

Foi criada uma classe de testes, que testava a compatibilidade com o laboratório passado e as novas funcionalidades

Classe Teste

public class teste extends junit.framework.TestCase
{
    public void testFuncionaComoOLab1() {
  //criando os objetos
  RelaQueue queue = new RelaQueue();
  Professor prof = new Professor(queue);
 
  // O que muda em termos de interface externa neste lab,
  // é a criação dos alunos. O que mostra que o nosso código
  // está bem desacoplado e a nossa refatoração não alterou
  // o funcionamento dos outros objetos (Professor, Relatório, etc).
    Aluno aluno1 = new Aluno("John Smith", queue);
    Aluno aluno2 = new Aluno("Mark Smith", queue);
    Aluno aluno3 = new Aluno("Joseph Smith", queue);
    Aluno aluno4 = new Aluno("Robert Smith", queue);
 try {
    aluno3.setComportamento( new SafoPreguicoso(aluno3) );
    aluno4.setComportamento( new SafoPreguicoso(aluno4) );
  } catch (Exception e) {
    fail("Não deveria lançar erro!");
  }
 
  //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();
}
 
public void testOsComportamentosFuncionamComoEspecificado() {
  RelaQueue queue = new RelaQueue();
  Aluno aluno1 = new Aluno("John", queue);
  Comportamento summa = new Summa(aluno1);
  Comportamento pemba = new Pemba(aluno1);
  Comportamento imprevisivel = new Imprevisivel(aluno1);
  Comportamento safo = new SafoPreguicoso(aluno1);
  Comportamento esforcado = new Esforcado(aluno1);
  Comportamento burro = new Burro(aluno1);
 
 //teste de esforcado
  assertEquals(0.5, esforcado.getInteligencia(), 0.01);
  assertEquals(1, esforcado.getDedicacao(), 0.01);
 
//teste de burro
  assertEquals(0.0, burro.getInteligencia(), 0.01);
  assertEquals(0.0, burro.getDedicacao(), 0.01);
 
//teste de summa
  assertEquals(1.0, summa.getInteligencia(), 0.01);
  assertEquals(1.0, summa.getDedicacao(), 0.01);
 
  //teste de safo
  assertEquals(1.0, safo.getInteligencia(), 0.01);
  assertTrue(safo.getDedicacao() != safo.getDedicacao()); //deve ser randomica
  assertTrue(safo.getDedicacao() < 0.5);
 
  //teste de imprevisivel
  assertTrue(imprevisivel.getInteligencia() != imprevisivel.getInteligencia()); //deve ser randomica
  assertTrue(imprevisivel.getInteligencia() < 1.0);
  assertTrue(imprevisivel.getDedicacao() != imprevisivel.getDedicacao()); //deve ser randomica
  assertTrue(imprevisivel.getDedicacao() < 1.0);
 
  //teste de pemba
  assertTrue(pemba.getInteligencia() != pemba.getInteligencia()); //deve ser randomica
  assertTrue(pemba.getInteligencia() < 0.5);
  assertTrue(pemba.getDedicacao() != pemba.getDedicacao()); //deve ser randomica
  assertTrue(pemba.getDedicacao() < 0.5);
 
}
 
public void testAsSubClassesDeAlunoTemRestricoes() {
    RelaQueue queue = new RelaQueue();
    AlunoITA alunoITA = new AlunoITA("John Smith", queue);
    AlunoUSP alunoUSP = new AlunoUSP("Mark Smith", queue);
    AlunoUnicamp alunoUnicamp = new AlunoUnicamp("Joseph Smith", queue);
 try {
    alunoITA.setComportamento( new SafoPreguicoso(alunoITA) );
    alunoITA.setComportamento( new Summa(alunoITA) );
    alunoUSP.setComportamento( new Burro(alunoUSP) );
    alunoUnicamp.setComportamento( new Burro(alunoUnicamp) );
  } catch (Exception e) {
    fail("Não deveria lançar erro!");
  }
 try {
    alunoITA.setComportamento( new Burro(alunoITA) );
  } catch (Exception e) {
      System.out.println("Iteano naum eh burro!");
  }
 try {
    alunoUSP.setComportamento( new SafoPreguicoso(alunoUSP) );
  } catch (Exception e) {
      System.out.println("USPeano naum eh safopreguicoso!");
  }
 try {
    alunoUnicamp.setComportamento( new Summa(alunoUnicamp) );
  } catch (Exception e) {
      System.out.println("Unicampeano naum eh summa!");
  }
}
 
public void testRelaQueueEhSubclasseDoGenericoQueue() {
  Queue<Relatorio> q = new RelaQueue(); //propriedade básica do polimorfismo
}
 
}

O esquema das Classes compiladas foi:

classes_compiladas.JPG

O resultado de TestAll na Classe de Testes foi:

janela_testes.JPGterminal1.JPG

Ao se fazer testes com interação com o usuário através do método main de Simulator, obtivemos:

terminal2.JPG

O projeto completo do laboratório é Laboratório 2.

Conclusão

A importância deste laboratório foi aplicar conceitos importante de Orientação a Objetos aprendidos em sala de aula. Tais conceitos, que podem ser aplicados em muitas situação, fizeram que o programa ficasse mais flexivel, como no caso dos genéricos. Outro conceito a meu ver extremamente importante usado foi o tratamento de Exceptions. O uso do mesmo torna o programa menos vulnerável a erros cometidos pelo usuário.

A única dificuldade na realização do laboratório foi o uso de genéricos, já que os slides da aula 6 não deixavam muito claro como implementar.

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License