Lab1 Livia

aluno: Nome do Aluno
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 06/08/2008 (2)

Introdução

Neste primeiro laboratório, criamos um projeto simples que simula confecção e entrega de relatórios por alunos e correção dos relas em ordem de chegada por um professor. O objetivo é trabalhar com conceitos básicos de orientação a objeto, como classes, métodos e tributos, herança, classe abstrata, controles de acesso, etc. Além disso, através deste trabalho também conhecemos características e sintaxe da linguagem Java e aprendemos a trabalhar com IDE's.

Desenvolvimento

O conceito mais importante aprendido neste lab foi o de herança de classes abstratas. Aplicou-se este conceito da seguinte forma:

Nas especificações do projeto, vemos dois tipos distintos de alunos: o Safo e Preguiçoso e o Esforçado. Ambos possuem atributos em comum (conhecimento, nome e fila de relas) e todos os métodos também em comum. Porém, alguns destes métodos realizam tarefas diferentes quanto invocados e há atributos exclusivos de um tipo de aluno que não existe no outro. Para criar objetos com estas características, adota-se o uso de herança de classe abstrata "Aluno". Toda a classe filha terá, então, os atributos e métodos comuns e terá os métodos declarado como abstrato na classe mãe especificados. É diferente de interface, pois com ela não é possível a "herança" de atributos comuns. Além disso, o fato da classe e dos métodos serem abstratos obriga o programador a extender a classe e declarar este métodos de forma específica para cada classe filha. Desta forma, aplicamos o conceito de polimorfismo usando herança para tratar entidades com características comuns e exclusivas.

Para ilustrar esta prática de programação, o código da classe "Aluno" segue abaixo. Note os métodos abstratos:

public abstract class Aluno {
 
    private int conhecimento;
    private String nome;
    private RelaQueue queue;
 
    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((float)qualidade,(float)originalidade,this);
        queue.queue(rela);
        this.conhecimento=this.conhecimento+1;
    }
 
    public int getConhecimento(){
        return conhecimento;
    }    
    public abstract float getInteligencia();
 
    public abstract float getDedicacao();
 
    public String getNome(){
        return nome;        
    }
 
    public Aluno(String nome, RelaQueue queue ){
        this.nome=nome;
        this.queue=queue;
        conhecimento=0;
    }
}

A classe "AlunoEsforçado" extende "Aluno". Note, no código abaixo, a chamada para o construtor "Aluno(String, RelaQueu)", além da declaração de dois novos parâmetros e a implementação dos métodos abstratos de "Aluno".

public class AlunoEsforcado extends Aluno{
 
    private float inteligencia;
    private float dedicacao;
 
    public AlunoEsforcado(String nome, RelaQueue queue) {
        super(nome,queue);
        inteligencia=(float)0.5;
        dedicacao=(float)1;
    }
    public float getInteligencia() {
        return inteligencia;
    }
    public float getDedicacao() {
        return dedicacao;
    }
}

O mesmo acontece com a classe "AlunoSafoPreguiçoso". Percebe-se que não há o atributo "dedicação" nesta classe e o método "getDedicação()" instancia um objeto da classe Random para gerar um valor randômico de dedicação entre 0.0 e 0.5. Nota-se também que o construtor chama o construtor da classe "Aluno(String, RelaQueue)", porém inclui também tarefas exclusivas para a construção desta classe.

public class AlunoSafoPreguicoso extends Aluno {
 
    private float inteligencia;
 
    public AlunoSafoPreguicoso(String nome, RelaQueue queue) {
        super(nome, queue);
        inteligencia = (float) 1;
    }
    public float getInteligencia() {
        return inteligencia;
    }
    public float getDedicacao() {
        Random randomGen = new Random();
        float random=randomGen.nextFloat();
        return random*((float)0.5);
    }
}

Ambas estas classes herdam o método "fazerEEntregarRela", que instancia um objeto da classe "Relatorio" de acordo com os parâmetros "dedicação" e "inteligência" de cada objeto "Aluno" responsável pela sua criação. Observamos que os parâmetros passados para o construtor "Relatorio(float, float, Aluno)" condiz com o método:

public Relatorio(float qualidade, float originalidade, Aluno aluno) {
        this.qualidade=qualidade;
        this.originalidade=originalidade;
        this.aluno=aluno;        
    }

O mesmo método que instancia um objeto "Relatorio", coloca este relalório na fila, através do método "queue(Relatorio)". Dentro da classe "Relagtorio", vemos que este método coloca o "Relatorio" passado no fim da array e muda o índice que mostra o fim da fila na array. Os atributos da classe "RelaQueue", seu construtor e o método "queue(Relatorio)" são:

private Relatorio array[];
    final static int ARRAY_LENGHT=10;
    private int inicio;
    private int fim;
 
    public RelaQueue() {
        array=new Relatorio[ARRAY_LENGHT];
        inicio=0;
        fim=0;    
    }    
    public void queue(Relatorio rela){
        array[fim]= rela;
        fim=(fim+1)%10;
    }

A última classe a ser analisada é a "Professor", cujo único parâmetro é a fila de relatórios da qual ele deve tirar relatórios para correção. Ele as corrige através de dois métodos, um para corrigir um só relatório e outro para corrigir todos da fila e retorna uma String com todas as notas. São eles, respectivamente:

private float corrigirRelatorio(Relatorio rela) {
        Random randomGen = new Random();
        double nota = ((double)rela.getQualidade() * (double)rela.getOriginalidade() * (randomGen.nextDouble()) / 3 * 10);
        return (float)nota;
    }    
    public String corrigirRelatorios(){
        String notas="Notas:\n\n";
        Relatorio rela=queue.dequeue();
        while(rela!=null){
            notas=notas+"\t"+rela.getAluno().getNome()+" = "+corrigirRelatorio(rela)+"\n";
            rela=queue.dequeue();
        }
        return notas;
    }

Finalmente, na classe Main, são declarados vários alunos diferentes, um professor e uma fila comum a todos. Além disso, declara-se também uma String onde serão acrescentados os resultados das chamadas de diversos métodos das classes aqui criadas. Após estas invocações, um tela (criada através do método estático da classe "JOptionPane") mostra esta String com os resultados:

JOptionPane

Além disso, foram realizados testes usando a biblioteca JUnit. Foram criadas classes de testes no pacote de testes do projeto no Netbeans e, a seguir, os métodos das classes do pacote fonte foram testados com sucesso. Abaixo, pode-se perceber que todas as etapas de testes foram bem-sucedidas e, além disso, no canto esquerdo, tem-se a visão da estrutura do projeto e seus pacotes:

Project

Os arquivos com o código de cada classe e o arquivo .rar com o projeto completo em NetBeans seguem abaixo:

Classe Aluno
Classe AlunoSafoPreguiçoso
Classe AlunoEsforçado
Classe Professor
Classe Relatorio
Classe RelaQueue
CES22_Lab1_Livia.rar

Conclusão

Com este exercício de laboratório, pudemos aprender na prática conceitos essencias para a programação orientada a objetos, como polimorfismo, herança, construtor de classe, métodos e atributos de classe e instanciação de objetos. Além disso, aprendi também algumas uma nova funcionalidade dos ambientes de desenvolvimento que desconhecia: o pacote de testes, usando JUnit.
Na prática, fica muito claro a organização que os paradigmas de OO proporcionam a qualquer projeto.

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