Bom, tenho o código abaixo, que tem a saída: “high high”
public class A{
private String runNow(){
return "High";
}
static class B extends A{
public String runNow(){
return "Low";
}
}
public static void main(String args[]){
A[] a=new B[]{new B(),new C()};
for(A aa:a)
System.out.print(aa.runNow()+" ");
}
}
class C extends A.B{
public String runNow(){
return "Out";
}
}
Eu imagino que o motivo seja o seguinte (Me corrijam se eu estiver errado) : Quando tentamos chamar o método “aa.runNow()” do objeto B, o compilador começa procurando pela superclasse (no caso a classe A) e como verifica que na classe A tem um método runNow() PRIVADO, ele já deduz que não haverá nenhum “override” para este método nas subclasses, por isso executa logo o runNow() da classe A.
O mesmo ocorre quando executamos o runNow() do objeto C, ele vai lá na classe A e verifica que o runNow() é privado e que não pode ser sobrescrito e executa logo. Ou seja, o conceito de polimorfismo não se aplica aqui, já que o runNow() da classe A é privado.
Ne verdade é sempre bom olhar o lado esquerdo da atribuição, ou nesse caso as referências criadas:
Nessa linha:
A[] a=new B[]{new B(),new C()};
Você está dizendo que tanto new B(), quanto new C() são A, e de fato o são.
Agora para que ele possa identificar os métodos runNow() proprio de cada filho de A, é necessário cast pois B e C sabem que são filhos de A, mas A não sabe que B e C são seus filhos, logo, não sabe da existência de runNow() neles, mas sim dele próprio.
Quanto a questão do método ser privado em A, tenha em mente que para outras classes ele não é acessível, você consegue executá-lo em main por rodar a aplicação na própria classe.
É para casos como esse que servem métodos abstratos na classe pai, aliás, sugiro você modificar sua classe A para ter o runNow() dessa forma:
public abstract class A{
private abstract runNow();
}
Creio que com isso você consegue resolver o problema, mas tenha em mente que o polimorfismo no primeiro caso ocorreu normalmente.
Mas a questão aqui é entender o seguinte: Porque quando eu chamo o runNow() da classe B ele executa o runNow() da classe A ? Minha ideia é que ele sempre começa procurando pelo método na superclasse, e como o mesmo é privado ele executa-o, caso contrário o método da classe B é executado.
Quando se declara um array do tipo A, ele só aceita elementos do tipo A confere? Sendo assim B e C também são tipo A.
Agora ele sempre busca o método runNow da classe A simplesmente por causa disso:
A[] a = ...
O java se baseia na referência para identificar os métodos que a classe possui, como você declarou runNow() concreto (com corpo para ser executado) ele irá executá-lo logo no primeiro que encontrou (o que é o lógico, pois se existe um método concreto na classe A, porque não executá-lo?), então ele nem perde tempo examinando quem está do outro lado da atribuição.
Por isso sugeri trocar sua classe para abstract e seu método runNow() também, pois isso força a jvm parar e pensar: “Opa, o programador declarou o método runNow() na classe A como abstrato… quer dizer que tem algum filho dele rodando esse método…”.
Como base nessa linha de pensamento a jvm pensa de novo: “Vou ver do outro lado da atribuição quais elementos tem esse método runNow() para eu executar…”
Pra ser sincero os exemplo com classes de nomes A, B, C confundem mais ainda, posso sugerir outro exemplo? Diga no seu próximo post se posso exemplificá-lo.
Amigo, é que esse exemplo é de uma questão da OCJP. Por isso quero tentar entendê-lo com exatidão. Mas vamos lá… (pode sugerir outro exemplo também, não tem problema)
Quando você disse “o que é o lógico, pois se existe um método concreto na classe A, porque não executá-lo?” eu penso que mesmo que tenha uma método concreto na classe A, pode haver outro método concreto na classe B (filha de A), então o correto seria ele executar o método da classe B por estar sobrescrevendo a classe A.
Olá
No caso não está “overridando” (para verificar basta testar com @Override).
Este é um caso de sobrecarga, está sendo criado um novo método com a mesma assinatura.
C está overridando B, para testar basta mudar de A[] para B[] na atribuição e no for