Sabemos que o método vencedores
está implementado na classe Jogo
de modo a devolver o(s) jogador(es) com melhor pontuação. Sabemos também que este método foi redefinido na classe JogoComObjetivo
de modo a devolver todos os jogadores que tenham alcançado a pontuação objetivo.
Na classe JogoNumeroExatoJogadas
não redefinimos este método, ou seja, o método vencedores
é herdado por esta classe exatamente como foi definido na classe Jogo
.
Qual das duas versões do método vencedores
é usada em cada uma das duas execuções (quando i
toma os valores zero e 1), da seguinte instrução no main
do exemplo da secção anterior?
xList<String> venceram = meusJogos[i].vencedores();
Depende!
Repare que,
embora o tipo declarado dos dois elementos do array meusJogos
seja Jogo
,
o tipo concreto de cada um deles não é exatamente esse
meusJogos[0]
é do tipo JogoComObjetivo
meusJogos[1]
é do tipo JogoNumeroExatoJogadas
.
É o mecanismo de ligação dinâmica (dynamic binding) que assegura que,
- na invocação de um método sobre um objeto, é a versão correta desse método que é executada;
- a versão correta é a que está acessível na classe a que o objeto pertence, ou seja, na do seu tipo concreto.
No nosso caso,
quando i
vale zero, o alvo da invocação do método vencedores
em meusJogos[i].vencedores()
é do tipo JogoComObjetivo
quando i
vale um, o alvo da invocação do método vencedores
em meusJogos[i].vencedores()
é do tipo JogoNumeroExatoJogadas
Jogo
(que é herdada pela classe JogoNumeroExatoJogadas
).Voltemos ao programa ExemploPolimorfismoParametros
da secção 15.1 e foquemo-nos agora na seguinte instrução do método imprimeVencedores
, que invoca o método vencedores
sobre o parâmetro j
:
xList<String> venceram = j.vencedores();
Qual das duas versões do método vencedores
é executada dentro do método imprimeVencedores
como resultado das seguintes invocações no main
?
ximprimeVencedores(jogo1);
imprimeVencedores(jogo2);
Aqui o raciocínio é o mesmo: depende!
na invocação imprimeVencedores(jogo1);
o parâmetro j
fica a referenciar um objeto do tipo JogoComObjetivo
vencedores
que é executada sobre o alvo j
dentro do método imprimeVencedores
é a que está redefinida nesta classe;na invocação imprimeVencedores(jogo2);
o parâmetro j
fica a referenciar um objeto do tipo JogoNumeroExatoJogadas
vencedores
que é executada sobre o alvo j
é a que está acessível na classe JogoNumeroExatoJogadas
, que é a versão que foi herdada da sua superclasse Jogo
.
Anterior: 15.2. Verificação estática de tipos
Seguinte: 15.4. Invocação indireta de métodos redefinidos