Ontem tive uma entrevista técnica por telefone de duas horas (na qual passei, uhuu!), Mas esqueci completamente a seguinte pergunta sobre vinculação dinâmica em Java. E é duplamente intrigante porque eu costumava ensinar esse conceito para alunos de graduação quando era um TA há alguns anos, então a perspectiva de que eu lhes dei informações erradas é um pouco perturbadora ...
Aqui está o problema que me foi dado:
/* What is the output of the following program? */
public class Test {
public boolean equals( Test other ) {
System.out.println( "Inside of Test.equals" );
return false;
}
public static void main( String [] args ) {
Object t1 = new Test();
Object t2 = new Test();
Test t3 = new Test();
Object o1 = new Object();
int count = 0;
System.out.println( count++ );// prints 0
t1.equals( t2 ) ;
System.out.println( count++ );// prints 1
t1.equals( t3 );
System.out.println( count++ );// prints 2
t3.equals( o1 );
System.out.println( count++ );// prints 3
t3.equals(t3);
System.out.println( count++ );// prints 4
t3.equals(t2);
}
}
Afirmei que a saída deveria ter sido duas instruções de impressão separadas de dentro do equals()
método substituído : at t1.equals(t3)
e t3.equals(t3)
. O último caso é bastante óbvio, e com o primeiro caso, embora t1
tenha uma referência do tipo Object, ele é instanciado como tipo Test, portanto a vinculação dinâmica deve chamar a forma substituída do método.
Aparentemente não. Meu entrevistador me incentivou a executar o programa sozinho e, vejam só, havia apenas uma única saída do método substituído: na linha t3.equals(t3)
.
Minha pergunta então é: por quê? Como já mencionei, embora t1
seja uma referência do tipo Object (então a vinculação estática invocaria o equals()
método de Object ), a vinculação dinâmica deve ter o cuidado de invocar a versão mais específica do método com base no tipo instanciado da referência. o que estou perdendo?