aluno: Lívia Palomo
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 03/11/2008 (6)
Introdução
Este laboratório se resume a portar o Lab2 para a linguagem Ruby. Como ambos os programas realizam as mesmas operações, o foco deste relatório será nas diferenças entre as linguagens.
Desenvolvimento
Para o desenvolvimento do programa, foi utilizado o IDE Netbeans, por ser mais simples do que a execução de comandos e interpretação de códigos Ruby via tela de comando.
Como Ruby permite uma liberdade maior na estrutura de arquivos, optei pela seguinte separação de classes entre arquivos:
1- Arquivo "aluno.rb": contém a classe "Aluno", as classes-filhas "Aluno_ITA", "Aluno_USP" e "Aluno_Unicamp", e todas as classes de comportamentos;
2- Arquivo "professor_e_rela.rb": contém as classes "Professor", "Queue" e "Relatorio";
3- Arquivo "simulador.rb": não contém classes, só a sequência de código necessária para a interação com o usuário;
4- Arquivo "teste.rb": contém todas as classes de testes;
Vamos analisar mais a fundo cada um dos arquivos, comentando as diferenças entre as classes em Java e em Ruby:
1) Arquivo "aluno.rb"
A classe "Aluno" é semelhante à classe correspondente em Java. Porém, como a tipagem é dinâmica, as variáveis de classe nunca são de um tipo específico como em Java e podem receber qualquer valor. O padrão para as funções getters e setters também é diferente em Ruby: por exemplo, a função "getNome()" em Java se torna "nome()" em Ruby e a função "setComportamento (Comportamento comp" se torna "comportamento=(comp)". Estas mudanças irão ocorrer em todas as classes em todos os arquivos.
O código da classe "Aluno" segue abaixo:
class Aluno def initialize(nome, queue) @nome = nome @queue = queue @comportamento = Esforcado.new(self) @conhecimento = 0 end def comportamento=(comp) @comportamento=comp end def conhecimento() return conhecimento end def nome() return @nome end def inteligencia() return @comportamento.inteligencia() end def dedicacao() return @comportamento.dedicacao() end def faz_e_entrega_rela() qualidade=(2*@comportamento.dedicacao()+@comportamento.inteligencia())/3 originalidade=(@comportamento.dedicacao()+2*@comportamento.inteligencia())/3 rela=Relatorio.new(qualidade, originalidade, self) @queue.queue(rela) @conhecimento=@conhecimento+1 end end
Como no Lab2, a classe "Aluno" possui 3 classes-filhas. Cada uma delas reescreve o método "comportamento=(comp)" para incluir restrições quanto ao comportamento de cada tipo de aluno. Estas restrições são implementadas usando, novamente, exceções, que em Ruby são mais simples de serem chamadas, pois não precisam ser instanciadas, como mostrado no código abaixo:
class Aluno_ITA < Aluno def inicialize(nome, queue) super(nome, queue) end def comportamento=(comp) if(comp.instance_of?(Burro)) raise "nao da" end @comportamento=comp end end
Já as classes de comportamento deixam de ser herança de uma classe abstrata "Comportamento" como em Java. Como esta classe abstrata no Lab2 só possuia métodos abstratos, ou seja, não carregava nenhuma informação consigo exceto a estrutura interna que uma classe-filha deveria ter para efeitos de compatibilidade, optei por criar classes independentes de comportamento. O restante do programa não fica prejudicado, pois a tipagem é dinâmica e, assim, a variável "@comportamento" da classe "Aluno" pode receber como valor uma instância de qualquer uma destas classes de comportamento. Já em Java, esta variável era do tipo "Comportamento" e poderia receber como argumento somente uma instância de uma classe concreta herdada de "Comportamento".
Segue abaixo o código do comportamento "Pemba" para ilustrar o que foi comentado acima:
class Pemba def initialize(aluno) @aluno=aluno end def inteligencia() return rand()*0.5 end def dedicacao() return rand()*0.5 end end
2) Arquivo "professor_e_rela.rb"
A classe "Professor" é muito semelhante à classe do Lab2, exceto pela sintaxe e padrões da linguagem Ruby. Por isso, dispensa comentários e apresentação do código. O mesmo acontece com a classe "Relatorio": a única diferença entre esta classe e a correspondente no Lab2 é a sintaxe, os padrões para getters e setters e, obviamente, a não-declaração de tipos das variáveis.
A classe "Queue", ao contrário, sofreu uma mudança significativa: deixou de ger genérica, pois este tipo de classe não faz sentido em uma linguagem com tipagem dinâmica. Os métodos internos são os mesmos e uma variável estática "@@queue_length" é usada para armazenar o tamanho da fila. Seu código segue abaixo:
class Queue @@array_length=10 def initialize() @array=Array.new @inicio=0 @fim=0 end def queue(obj) @array[@fim]=obj @fim=(@fim+1)%@@array_length end def dequeue() if(vazia?()) return nil end obj=@array[@inicio] @inicio=(@inicio+1)%@@array_length return obj end def vazia?() if(@inicio==@fim) return true end return false end end
3) Arquivo "simulador.rb"
O arquivo do simulador não possui nenhuma classe, o que evidencia uma importante diferença entre Ruby e Java, já que esta última não aceita arquivos sem classes nem permite a execução de códigos que estão fora de uma método de classe.
Os comandos de loop e de leitura e escrita de strings na tela são bem mais simples e intuitivos que em Java. Abaixo, segue um trecho do código do simulador que ilustra estas simplicidades:
loop do sair=false resp=nil puts "\n?? Deseja adicionar um novo aluno? (s/n): " begin resp = gets().chomp if (resp.eql?("n")||resp.eql?("N")) sair=true break end end while(!(resp.eql?("s")||resp.eql?("S"))) if (sair==true) break end
O simulador funciona muito bem, como pode ser comprovado pela screenshot a seguir:
4) Arquivo "teste.rb"
O código de testes é idêntico ao aplicado ao Lab2, exceto por diferenças de sintaxe, e, por isso, não terá seu código apresentado aqui.
Todos os testes foram bem-sucedidos, como mostrado no screenshot abaixo:
Arquivos do Projeto
O pacote do projeto está AQUI
Conclusão
Este laboratório foi muito interessante, pois permitiu nosso contato com a linguagem Ruby. A programação é Ruby é muito mais simples, pois possui muito menos regras e estruturas fixas.
Porém, percebi que esta falta de regras e o fato do código não ser compilado exige uma atenção especial do programador.