Reveja a seguir o exemplo de polimorfismo e amarração dinâmica em C++. Estude este exemplo e tente escrevê-lo em Java na célula abaixo.
Algumas coisas importantes:
virtual
em C++.#include <iostream>
class Poligono {
private:
int altura;
int largura;
public:
Poligono(int altura, int largura) {
this->altura = altura;
this->largura = largura;
}
int getAltura() {
return altura;
}
int getLargura() {
return largura;
}
virtual float getArea() {
return 0;
}
};
class TrianguloRetangulo : public Poligono {
public:
TrianguloRetangulo(int altura, int largura) : Poligono(altura, largura) {
}
float getArea() {
return getAltura() * getLargura() / 2;
}
};
class Retangulo : public Poligono {
public:
Retangulo(int altura, int largura) : Poligono(altura, largura) {
}
float getArea() {
return getAltura() * getLargura();
}
};
Poligono *tr = new TrianguloRetangulo(6, 10);
Poligono *rt = new Retangulo(6, 10);
std::cout << "Área do triangulo retângulo: " << tr->getArea() << std::endl;
std::cout << "Área do retângulo: " << rt->getArea() << std::endl;
In [ ]:
In [1]:
class Poligono {
private int altura;
private int largura;
public Poligono(int altura, int largura) {
this.altura = altura;
this.largura = largura;
}
int getAltura() {
return altura;
}
int getLargura() {
return largura;
}
float getArea() {
return 0;
}
}
class TrianguloRetangulo extends Poligono {
public TrianguloRetangulo(int altura, int largura) {
super(altura, largura);
}
float getArea() {
return getAltura() * getLargura() / 2;
}
};
class Retangulo extends Poligono {
public Retangulo(int altura, int largura) {
super(altura, largura);
}
float getArea() {
return getAltura() * getLargura();
}
};
Poligono tr = new TrianguloRetangulo(6, 10);
Poligono rt = new Retangulo(6, 10);
System.out.println("Área do triangulo retângulo: " + tr.getArea());
System.out.println("Área do retângulo: " + rt.getArea());
toString()
no Garoto ZumbiVeja abaixo como a classe GarotoZumbi
foi modificada. O método mostra()
que mostrava o zumbi no console foi substituído pelo método toString()
que retorna uma String com o desenho do zumbi (mas não o imprime). Com essa nova versão, você precisa receber e imprimir no console da seguinte maneira:
System.out.println(garoto.toString());
Os outros métodos também deixaram de imprimir o desenho do zumbi e agora você precisa fazê-lo explicitamente.
In [2]:
public class GarotoZumbi
{
protected int idade;
protected String estado;
protected String nome;
public GarotoZumbi(int idade, String estado, String nome) {
this.idade = idade;
this.estado = estado;
this.nome = nome;
}
public String toString(boolean imprimeNome) {
String resultado = "";
// cabeleira
if (idade >= 2)
resultado += " *\n";
// corpo com olhos
if (estado.equalsIgnoreCase("acordado"))
resultado += " o*o\n";
else
resultado += " -*-\n";
// barba
if (idade >= 3)
resultado += "*****\n";
if (imprimeNome) {
resultado += nome + "\n";
resultado += "\n";
}
return resultado;
}
public String toString() {
return toString(true);
}
public void cresce() {
if (idade < 3)
idade++;
}
public void acorda() {
estado = "acordado";
}
public void dorme() {
estado = "dormindo";
}
}
GarotoZumbi garoto = new GarotoZumbi(1, "acordado", "Asdrubal");
System.out.println(garoto.toString());
garoto.dorme();
System.out.println(garoto.toString());
garoto.cresce();
System.out.println(garoto.toString());
toString()
de Object
O nome do método toString()
não foi escolhido por acaso. Ele é um método que está defininido na classe especial Object
, que é aquela classe de onde descencem implicitamente todas as classes. Quando você não sobrescreve o método toString()
ele retorna uma String o endereço do objeto na memória.
O método toString()
é chamado implicitamente toda vez que você pede para imprimir um objeto sem indicar o método, portanto, no exemplo a seguir:
Poligono tr = new TrianguloRetangulo(6, 10);
System.out.println(tr);
Poligono rt = new Retangulo(6, 10);
System.out.println(rt);
Ele imprime umas sequências estranhas que são a identificação única do objeto na memória.
Entretanto, se você sobrescreve o método toString()
, através do polimorfismo, o novo método será chamado implicitamente quando você pede para imprimir o objeto. Por exemplo:
GarotoZumbi garoto = new GarotoZumbi(1, "acordado", "Asdrubal");
System.out.println(garoto);
garoto.dorme();
System.out.println(garoto);
garoto.cresce();
System.out.println(garoto);
Imprime o desenho do GarotoZumbi
.
In [3]:
Poligono tr = new TrianguloRetangulo(6, 10);
System.out.println(tr);
Poligono rt = new Retangulo(6, 10);
System.out.println(rt);
System.out.println("===============================");
GarotoZumbi garoto = new GarotoZumbi(1, "acordado", "Asdrubal");
System.out.println(garoto);
garoto.dorme();
System.out.println(garoto);
garoto.cresce();
System.out.println(garoto);
Considere os herdeiros Monstro
e Perfeito
abaixo implementados à moda antiga com o método mostra()
(eles não funcionarão agora se você tentar executá-los porque a superclasse -- GarotoZumbi
-- não tem mais o mostra()
).
Adapte ambos para que passem a ter o método toString()
que retorna o desenho na forma de String, substituindo o mostra()
.
In [7]:
public class Monstro extends GarotoZumbi
{
public Monstro(int idade, String estado, String nome) {
super(idade, estado, nome);
}
public String toString(boolean imprimeNome) {
String resultado = super.toString(false);
if (idade >= 4)
resultado += "#####\n";
if (idade >= 5)
resultado += "/ \\\n";
if (imprimeNome) {
resultado += nome + "\n";
resultado += "\n";
}
return resultado;
}
public void cresce() {
if (idade < 5)
idade++;
}
}
Monstro monst = new Monstro(1, "acordado", "Bonerges");
System.out.println(monst);
monst.cresce();
System.out.println(monst);
monst.cresce();
System.out.println(monst);
monst.cresce();
System.out.println(monst);
monst.cresce();
System.out.println(monst);
monst.cresce();
System.out.println(monst);
monst.dorme();
System.out.println(monst);
In [10]:
public class Perfeito extends GarotoZumbi
{
private String situacao = "normal";
public Perfeito(int idade, String estado, String nome) {
super(idade, estado, nome);
}
public Perfeito(int idade, String estado, String nome, String situacao) {
super(idade, estado, nome);
this.situacao = situacao;
}
public String toString() {
String resultado = "+-----+\n";
if (idade >= 2)
resultado += "| |\n";
if (estado.equals("dormindo")) {
resultado += " - -\n";
resultado += "| _ |\n";
}
else if (situacao.equals("normal")) {
resultado += "| o-o |\n";
resultado += "| ___ |\n";
}
else if (situacao.equals("milionario")) {
resultado += "| $-$ |\n";
resultado += "| ___ |\n";
}
else if (situacao.equals("doido")) {
resultado += "| @-@ |\n";
resultado += "| ~ |\n";
}
if (idade < 3)
resultado += " \\___/\n";
else {
resultado += "| |\n";
resultado += "\\_____/\n";
}
resultado += nome + "\n\n";
return resultado;
}
public void mudaSituacao() {
String s[] = {"normal",
"milionario",
"doido" };
int p;
for (p = 0; p < s.length && !situacao.equals(s[p]); p++)
/* nada */ ;
p = (p + 1) % 3;
situacao = s[p];
}
}
Perfeito perf = new Perfeito(1, "acordado", "Zandor");
System.out.println(perf);
perf.cresce();
System.out.println(perf);
perf.cresce();
System.out.println(perf);
perf.mudaSituacao();
System.out.println(perf);
perf.mudaSituacao();
System.out.println(perf);
Dada a classe Servicos
, a seguir, crie nela um método estático chamado imprimeZumbi
. Esse método deve receber como parâmetro uma referência para um objeto da classe GarotoZumbi
(considere a nova versão com toString()
), ou um de seus herdeiros, e deve imprimi-lo.
Utilize uma solução que explore o polimorfismo, sem o uso de condicional.
In [14]:
public class Servicos {
public static void imprimeZumbi(GarotoZumbi garoto) {
System.out.println(garoto);
}
}
Monstro monst = new Monstro(2, "dormindo", "Bonerges");
Servicos.imprimeZumbi(monst);
Perfeito perf = new Perfeito(1, "acordado", "Zandor");
Servicos.imprimeZumbi(perf);
Dada a classe EmprestimoComposto
desenvolvida anteriormente em sala de aula.
Crie uma classe Emprestimo
que generalize qualquer emprestimo e EmprestimoComposto
passa a ser herdeira da mesma. Transfira para a superclasse o máximo de atributos e métodos, de tal modo que possam ser reusados pelos herdeiros.
Crie uma classe EmprestimoSimples
herdeira de Emprestimo
que também disponha dos métodos parcela()
e proximaParcela()
.
In [1]:
import java.lang.Math;
class EmprestimoComposto {
private float s;
private int n;
private float j;
private int corrente;
private float p,
proxima;
public EmprestimoComposto(float s, int n, float j) {
this.s = s;
this.n = n;
this.j = j;
corrente = 1;
this.p = -1; // antes da primeira parcela
this.proxima = s;
}
float getS() {
return s;
}
int getN() {
return n;
}
float getJ() {
return j;
}
public float proximaParcela() {
p = proxima;
corrente++;
if (corrente <= n)
proxima += (proxima * (j/100));
else
proxima = 0;
return p;
}
public float parcela() {
return p;
}
public float parcela(int numero) {
float resultado = 0;
if (numero <= n)
resultado = s * (float)Math.pow(1 + j/100, numero-1);
return resultado;
}
}
// codigo principal
EmprestimoComposto emprestimo1 = new EmprestimoComposto(200, 5, 1),
emprestimo2 = new EmprestimoComposto(500, 7, 2);
int i = 1;
emprestimo1.proximaParcela();
emprestimo2.proximaParcela();
while (emprestimo1.parcela() > 0 || emprestimo2.parcela() > 0) {
if (emprestimo1.parcela() > 0) {
System.out.println("Emprestimo 1: parcela " + i + " eh " + emprestimo1.parcela());
System.out.println(" parcela " + i + " eh " + emprestimo1.parcela(i));
}
if (emprestimo2.parcela() > 0) {
System.out.println("Emprestimo 2: parcela " + i + " eh " + emprestimo2.parcela());
System.out.println(" parcela " + i + " eh " + emprestimo2.parcela(i));
}
emprestimo1.proximaParcela();
emprestimo2.proximaParcela();
i++;
}
In [ ]:
In [ ]: