Contents |
Os seguintes exemplos estão escritos em Java.
As seguintes classes descrevem uma hierarquia: o conceito mais abstracto é o de animal, seguido de mamífero, seguido de gato (o conceito mais específico).
nadar
. Este método é definido em todas as classes pois admitiu-se que cada tipo de animal tem uma forma especial de nadar.Animal
define o método irPara
. Este método é definido como final
pois admitiu-se que é suficientemente genérico para todos os animais.Gato
define o método miar
(a acção não é suficientemente geral para ser definida a um nível superior).A definição da classe Animal
é como se segue:
class Animal {
final void irPara(int p) {
System.out.println("Animal: deslocação para " + p);
}
void nadar() {
System.out.println("Animal: nadar");
}
}
A definição da classe Mamífero é como se segue:
class Mamífero extends Animal {
void nadar() {
System.out.println("Mamífero: nadar");
}
}
A definição da classe Gato
é como se segue:
class Gato extends Mamífero {
void nadar() {
System.out.println("Gato: nadar");
}
void miar() {
System.out.println("Gato: miar");
}
}
No exemplo seguinte demonstra-se um caso simples de polimorfismo assim como de binding. O exemplo de polimorfismo pode ser observado na iniciação da referência animal
: em lugar de referenciar um objecto da classe Animal
, referencia um objecto da classe Gato
. Este procedimento é admissÃvel para quaisquer referências e objectos, desde que o tipo associado à referência esteja ao mesmo nível hierárquico, ou acima, que o tipo associado ao objecto (i.e., seria admissÃvel a uma referência do tipo Animal
referenciar um objecto do tipo Mamífero
ou uma do tipo Mamífero
referenciar um objecto do tipo Gato
).
O conceito de binding pode ser observado na selecção dos métodos irPara
(early binding) e nadar
(late binding).
public class Teste {
public static void main(String[] args) {
Animal animal = new Gato();
Gato gato = new Gato();
animal.irPara(22); // irPara é final em Animal: early binding
animal.nadar(); // nadar é seleccionado durante a execução: late binding
//animal.miar(); // Erro de compilação: não há miar em Animal
((Gato)animal).miar(); // downcast
gato.irPara(33);
gato.nadar();
gato.miar();
}
}
O resultado é o seguinte:
Animal: deslocação para 22 Gato: nadar Gato: miar Animal: deslocação para 33 Gato: nadar Gato: miar
Note-se que, no late binding, é o tipo do objecto e não o da referência que determina o método a invocar. No early binding, i.e., para métodos final
(recorde-se que métodos private
são implicitamente final
) e static
, é o tipo da referência que define o método a invocar (em tempo de compilação). Veja-se o exemplo seguinte.
O aspecto da selecção do método a executar através de late binding é importante na medida em que contribui para a uniformização do código.
No exemplo seguinte, a invocação de nadar
é efectuada uniformemente.
class Teste {
public static void main(String[] args) {
Animal[] v = { new Animal(), new Mamífero(), new Gato() };
for (Animal a: v) a.nadar();
}
}
O resultado é o seguinte:
Animal: nadar Mamífero: nadar Gato: nadar
Como se pode apreciar, o vector contém referências para animais não especificados. No entanto, a invocação do método nadar
é feita de acordo com a classe do objecto.
Considere-se agora a aplicação de downcasts:
class Teste {
public static void main(String[] args) {
Animal[] v = { new Animal(), new Mamífero(), new Gato() };
// v[0].miar(); // erro de compilação
// v[1].miar(); // erro de compilação
// v[2].miar(); // erro de compilação
// ((Gato)v[0]).miar(); // excepção ClassCastException (erro durante a execução)
// ((Gato)v[1]).miar(); // excepção ClassCastException (erro durante a execução)
((Gato)v[2]).miar();
}
}
A execução de downcasts inválidos, i.e., conversão para tipos incompatíveis (como se pode observar na linhas 7 e 8 do exemplo), implica a ocorrência de erros em tempo de execução.
Erro de execução, caso o primeiro cast fosse descomentado:
Exception in thread "main" java.lang.ClassCastException: Animal at Teste.main(Teste.java:7)
Erro de execução, caso o segundo cast fosse descomentado:
Exception in thread "main" java.lang.ClassCastException: Mamífero at Teste.main(Teste.java:8)
Resultado sem erros:
Gato: miar