Dúvia sobre polimorfismo

Dado o código:

[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)

Opa brother…blz?

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.

Espero que eu tenha conseguido ajudar :slight_smile:

Qq coisa pergunta aew ;]

Abs
Well

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?

blobwell wrote:

Faz diferença sim … se voce criar um objeto SuperBase em c1,
Por exemplo.

Ele irá chamar o método print do construtor SuperBase, pois o sua classe pai de Derived é Base …

Então os parâmetro que você oferece faz diferença sim … pq as classes filhas não herdam diretamente da mesma classe pai.

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

Boiei :roll:

rsrs

hummmmmmmmmmmm

Havia ficado encucado com o Post do Silva e então fiquei queimando aqui alguns neurônios para entender. E consegui :smiley:

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. :slight_smile:

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.

Confuso né?rsrs Mas prestando atenção faz sentido :slight_smile:

Não boio não …

É como o nosso amigo rissato falou …

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.

É meio confuso … masss … é isso ai …

Se mesmo assim não ficou claro …

Grita aeee

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:

Também aprendi nesse tópico xD

[]´s
Precisando tamo aew \o/
Well

Correto

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 …

All right …

Espero q para todos ficou claro …

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)…

Na realidade os métodos estão sobrecarregados…

Pegadinha furiosa! =D

agora que to vendo… li tudo errado

qdo faz:

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

isso mesmo…
b1 e c1 estão com a visão restritas ao tipo de objeto declarado e não ao objeto instanciado…

é um caso de OVERLOADING…entao o metodo escolhido sempre é da SUPER!

Se voce, por exemplo, mudar o parametro de print para

void print(int a)

nem compila!

Pois, nesses casos, sempre o método da SUPER classe é executado.
O static na classe mais abaixo nao faz diferenca alguma.

Relamente uma questão foda!

principalmente se voce mudar as opções e ir vendo os resuldados!

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)

Muito legal essa questão =)