Polimorfismo

Considere o seguinte exemplo ilustrativo.

Classe Emprestimo

Retomando o exercício anterior, considere a seguinte classe que representa um Emprestimo, em que:

  • S - valor da primeira parcela
  • N - número de parcelas
  • J – percentual de juros mensal

Cada nova parcela é sempre calculada em relação à anterior:

  • Patual = Panterior mais Juros

In [1]:
public class Emprestimo {
   float s;
   int   n;
   float j;
   int   corrente;
   float p;

   Emprestimo(float s, int n, float j) {
      this.s = s;
      this.n = n;
      this.j = j;
      corrente = 1;
      this.p = s;
   }

   float proximaParcela() {
      float retorno = p;
      corrente++;
      if (corrente <= n)
         p = p + (p * (j/100));
      else
         p = 0;
      return retorno;
   }
}


Out[1]:
com.twosigma.beaker.javash.bkrec7f8663.Emprestimo

Empréstimo com Taxa de Administração (EmprestimoTA)

Taxa de valor fixo adicionada sobre o valor do empréstimo.

Sobrescrita de método

Método proximaParcela() tem mesma assinatura da superclasse e, portanto, sobrescreve a superclasse.


In [5]:
public class EmprestimoTA extends Emprestimo {
   private float ta;
   
   EmprestimoTA(float s, int n, float j, float ta) {
      super(s, n, j);
      this.ta = ta;
   }
   
   public float getTa() {
      return ta;
   }
   
   public float proximaParcela() {
      float pp = super.proximaParcela();
      if (pp > 0)
         pp += ta;
      return pp;
   }
}


Out[5]:
com.twosigma.beaker.javash.bkrec7f8663.EmprestimoTA

Usando métodos sobrescritos

Para um objeto da subclasse B, um método sobrescrito em B tem prioridade sobre o mesmo método da superclasse.


In [6]:
Emprestimo empST = new Emprestimo(200, 5, 1);
EmprestimoTA empCT = new EmprestimoTA(200, 5, 1, 15);

int i = 1;
float pst = empST.proximaParcela();
float pct = empCT.proximaParcela();
while (pst > 0 || pct > 0) {
   if (pst > 0)
      System.out.println("Emprestimo sem taxa: parcela " + i + " eh " + pst);
   if (pct > 0)
      System.out.println("Emprestimo com taxa: parcela " + i + " eh " + pct);
   pst = empST.proximaParcela();
   pct = empCT.proximaParcela();
   i++;
}


Emprestimo sem taxa: parcela 1 eh 200.0
Emprestimo com taxa: parcela 1 eh 215.0
Emprestimo sem taxa: parcela 2 eh 202.0
Emprestimo com taxa: parcela 2 eh 217.0
Emprestimo sem taxa: parcela 3 eh 204.02
Emprestimo com taxa: parcela 3 eh 219.02
Emprestimo sem taxa: parcela 4 eh 206.06021
Emprestimo com taxa: parcela 4 eh 221.06021
Emprestimo sem taxa: parcela 5 eh 208.12082
Emprestimo com taxa: parcela 5 eh 223.12082
Out[6]:
null

Polimorfismo

Propriedade de se apresentar ou tomar formas diversas.

"Habilidade das mais importantes dos sistemas orientados a objetos, e que consiste em as operações automaticamente se adequarem aos objetos aos quais estão sendo aplicadas." (Meyer, 1997)

Meyer, Bertrand (1997) Object-Oriented Software Construction – Second Edition. USA, Prentice-Hall, Inc.

Princípio para o Polimorfismo

Uma variável declarada em uma classe A pode ser instanciada em qualquer subclasse B.

Nesse caso, só estarão “visíveis”(respeitadas as regras de encapsulamento):

  • Atributos e métodos da superclasse A
  • Métodos sobrescritos da subclasse B

O contrário não é possível: Uma variável declarada em uma subclasse B não pode ser instanciada em sua superclasse A.


In [7]:
Emprestimo empST = new Emprestimo(200, 5, 1);
Emprestimo empCT = new EmprestimoTA(200, 5, 1, 15);

int i = 1;
float pst = empST.proximaParcela();
float pct = empCT.proximaParcela();
while (pst > 0 || pct > 0) {
   if (pst > 0)
      System.out.println("Emprestimo sem taxa: parcela " + i + " eh " + pst);
   if (pct > 0)
      System.out.println("Emprestimo com taxa: parcela " + i + " eh " + pct);
   pst = empST.proximaParcela();
   pct = empCT.proximaParcela();
   i++;
}


Emprestimo sem taxa: parcela 1 eh 200.0
Emprestimo com taxa: parcela 1 eh 215.0
Emprestimo sem taxa: parcela 2 eh 202.0
Emprestimo com taxa: parcela 2 eh 217.0
Emprestimo sem taxa: parcela 3 eh 204.02
Emprestimo com taxa: parcela 3 eh 219.02
Emprestimo sem taxa: parcela 4 eh 206.06021
Emprestimo com taxa: parcela 4 eh 221.06021
Emprestimo sem taxa: parcela 5 eh 208.12082
Emprestimo com taxa: parcela 5 eh 223.12082
Out[7]:
null

Para que serve o Polimorfismo?

Como controlar um conjunto de empréstimos heterogêneos?

Classe ConjuntoEmprestimos

A classe denominada ConjuntoEmprestimos é responsável por controlar um conjunto de empréstimos. Essa classe deve definir pelo menos os seguintes métodos:

  • construtor - recebe como parâmetro o número máximo de empréstimos;
  • adicionaEmprestimo - recebe como parâmetro um objeto da classe empréstimo e o armazena (se não ultrapassar o número máximo);
  • proximasParcelas - mostra as próximas parcelas de todos os empréstimos cadastrados (para fins de simplificação, considere que o número da próxima parcela é igual para todos); o método retorna um status de verdadeiro se houve pelo menos um empréstimo com próxima parcela.

In [3]:
public class ConjuntoEmprestimos {
   Emprestimo vEmprestimos[];
   int corrente = -1;
   
   ConjuntoEmprestimos(int quantidade) {
      vEmprestimos = new Emprestimo[quantidade];
   }
   
   boolean adicionaEmprestimo(Emprestimo emp) {
      boolean resultado = false;
      if (corrente+1 < vEmprestimos.length) {
         corrente++;
         vEmprestimos[corrente] = emp;
         resultado = true;
      }
      return resultado;
   }
   
   boolean proximasParcelas() {
      boolean status = false;
      for (int e = 0; e < vEmprestimos.length; e++) {
         float p = vEmprestimos[e].proximaParcela();
         if (p > 0) {
            status = true;
            System.out.println("Emprestimo " + (e+1) + ": " + p);
         }
      }
      return status;
   }
}


Out[3]:
com.twosigma.beaker.javash.bkrec7f8663.ConjuntoEmprestimos

Princípio do Polimorfismo no Vetor

  • Um vetor declarado em uma superclasse A pode receber instâncias de A e instâncias de quaisquer herdeiros de A.
  • Seguindo esse princípio, o vetor permite misturar instâncias de classes diferentes.

In [8]:
ConjuntoEmprestimos ce = new ConjuntoEmprestimos(5); 

ce.adicionaEmprestimo(new Emprestimo(200, 3, 1));
ce.adicionaEmprestimo(new EmprestimoTA(500, 4, 2, 15));
ce.adicionaEmprestimo(new Emprestimo(300, 2, 1));
ce.adicionaEmprestimo(new Emprestimo(450, 3, 2));
ce.adicionaEmprestimo(new EmprestimoTA(700, 2, 3, 10));

boolean status;
do {
   status = ce.proximasParcelas();
} while (status);


Emprestimo 1: 200.0
Emprestimo 2: 515.0
Emprestimo 3: 300.0
Emprestimo 4: 450.0
Emprestimo 5: 710.0
Emprestimo 1: 202.0
Emprestimo 2: 525.0
Emprestimo 3: 303.0
Emprestimo 4: 459.0
Emprestimo 5: 731.0
Emprestimo 1: 204.02
Emprestimo 2: 535.2
Emprestimo 4: 468.18
Emprestimo 2: 545.604
Out[8]:
null