[code]class SuperBase {
void print(SuperBase a) {
System.out.print("SUPER ");
}
}
class Base extends SuperBase {
void print(Base b) {
System.out.print("BASE ");
}
}
class Derived extends Base {
static void print(Derived c) {
System.out.print(“DERIVED”);
}
}
class Test {
public static void main (String[] args) {
SuperBase a1 = new SuperBase();
SuperBase b1 = new Base();
Base c1 = new Derived();
a1.print(new Base());
b1.print(new Derived());
c1.print(new Derived());
}
}[/code]
E a saída : SUPER SUPER BASE
Podemos assumir que, independentemente do tipo de parâmetro usado para chamar b1.print(), todas as vezes teremos SUPER como resposta ???
nesse seu exemplo sim … sempre que passarmos pelos construtores filhos, o pai é chamado (se ao inves disso chamasse this(), uma hora cairia em um construtor que chamaria o pai implicitamente)
Então… Independemente de qual dessas classes você ofereça como parâmatro, b1.print vai responder “SUPER”. Isso acontece pelo seguinte:
Quando você instanciou B, mesmo que vc tenha criado uma nova base, vc declarou B como sendo SuperBase. Ou seja, se ele é superbase, rodará o método da SuperBase, não de seus “filhos”.
No caso, os métodos print estão recebendo argumentos, mas indiferentemente do parâmetro que você ofereça, o parâmetro não está sendo utilizado para nada dentro do método. Nem um tipo de validação ou teste é feito, logo rodará somente o System.out.print(“Super”), independentemente do parâmetro.
Acho que eu descobri sobre o que era minha dúvida. No caso a cima estamos falando de OVERLOAD e não OVERRIDE. Se estivéssimos usando OVERRIDE no print(), aí sim a saída seria BASE, mesmo a referência sendo SuperBase. Estou certo?
Eita… eu achei que sabia e não sabia… :shock:
Não entendi como pode uma classe instanciada como Base rodar um método de superbase tendo um método com mesmo nome na Base. Ou seja, um método explicitamente definido com o mesmo nome, causando o polimorfismo e sem fazer qualquer tipo de código ou citação ele sair rodando o método do pai…o.O
Havia ficado encucado com o Post do Silva e então fiquei queimando aqui alguns neurônios para entender. E consegui
Acontece o seguinte:
class Test {
public static void main (String[] args) {
SuperBase a1 = new SuperBase();
SuperBase b1 = new Base();
Base c1 = new Derived();
a1.print(new Base());
b1.print(new Derived());
c1.print(new Derived());
}
}
No caso de c1, ele é Base. Portanto, ele herda da SuperBase o método print(SuperBase a). Portanto ele tem dois métodos: print(SuperBase a) e print(Base b). Logo, se vc invocar print(new SuperBase()) o método que vc estará invocando será o método herdado. Contudo, quando você passa como parâmetro “new Derived”, vc está invocando um método que é filho de Base. Como a instância c1 é de uma classe Base, ele vai rodar o método print que recebe como argumento uma classe base. Derived é filho de base, portanto com Derived como parâmetro roda o método de Base. Já com SuperBase como parâmetro roda um método que não chegou a ser definido no Base, mas que o pai possui, que seria o método print com SuperBase como parâmetro.
Melhor esclarecendo:
rsrs
quando você passa como parâmetro “new Derived”, vc está invocando O MÉTODO de Base. Ou seja, como a instância c1 é de uma classe Base, ele vai rodar o método print que recebe como argumento uma classe base. Derived é filho de base, portanto Derived é Base e, como parâmetro, roda o método de Base. Já com SuperBase como parâmetro, roda um método que não chegou a ser definido no Base, mas que o pai possui, que seria o método print com SuperBase como parâmetro.
Trata-se de Overload do método … vai depender do argumento do método.
Nesse caso em c1.print();
Voce instanciar um objeto SuperBase … a saida será SUPER … mas se vc instanciar um objeto Base … a saída será BASE … e se vc instanciar um objeto Derived … a saida será BASE por causa do sua classe pai.
Ou seja, concluindo e voltando a pergunta inicial…rsrs
class Test {
public static void main (String[] args) {
SuperBase a1 = new SuperBase();
SuperBase b1 = new Base();
Base c1 = new Derived();
a1.print(new Base());
b1.print(new Derived());
c1.print(new Derived());
}
}
b1 é filho de SuperBase. Portanto possui somente o método print que recebe como argumento um objeto SuperBase. Logo, como Base e Derived também são SuperBase, rodará o método print único existente, que no caso é o print que recebe como argumento o SuperBase. Portando, no caso de b1 nesse exemplo não importa o parâmetro: A resposta será sempre “Super”…
Espero ter esclarecido… uhahuahu
E desculpa a primeira postagem equivocada :oops:
Só completando … como Derived també é um Base … então ele pode receber como argumento o objeto Derived invocando assim o método de seu pai … por isso a saída é BASE …
O caso é que não ocorre OVERRIDE… os métodos tem assinaturas diferentes, então a classe Base possui 2 métodos print e a calsse Derived possui 3 (herança dos pais)…
SuperBase b1 = new Base();
Base c1 = new Derived();
b1 nao pode acessar o método print() de Base() e nem c1 pode acessar o método print() de Derived()… isso porque mesmo em tempo de execução a JVM sabendo que b1 referencia a Base(), ele nao pode chama-lo
Não é por acaso que o método escolhido é sempre do super não… preste atenção na declaração das variáveis:
SuperBase a1 = new SuperBase();
SuperBase b1 = new Base();
Base c1 = new Derived();
a1 é SuperBase
b1 é SuperBase
c1 é Base
Se estamos atribuindo objetos do tipo deles mesmos ou filhos, isso não importa… Pois a visão dos métodos em a1, b1 e c1 vai seguir a declaração do TIPO de objeto que a variável é…
Sabemos que um filho pode ser tranquilamente um pai, mas o contrário que não é válido…
A pegadinha mais furiosa é a saida
c1.print(new SuperBase());
Aí entra o OVERLOADING onde c1 sendo Base, conhece tanto seu método print como o método print de seu pai (assinaturas dos métodos são diferentes, por isso não ocorre OVERRIDE)