dúvida - subtipagem e casts

Oi galera…
tenho estas classes


public class Pai {
	Pai() {};
	String m () {
		return "metodo sobrescrito -- PAI";
	}
	String n (){
		return "metodo nao sobrescrito -- classe pai";
	}
}

public class Filho extends Pai {
	Filho() {};
	String m () {
		return "metodo sobrescrito -- FILHO";
	}
	
}


public class teste {
	public static void main(String[] args) {
		Pai pai = null;
		Pai p = new Pai();
		Filho filho = new Filho();
		if (filho instanceof Pai) {
			pai = filho;
			p = (Pai)filho;
			if (filho == pai)
				System.out.println("true");
			else
				System.out.println("false");
			
			//achei que fosse imprimir o método da clase pai
			System.out.println(((Pai)pai).m());
			//achei que não ia conseguir enxergar o método
			System.out.println(pai.n());
			//achei que fosse imprimir o método da clase pai
			System.out.println(p.m());
		}
	}
}

o que imprime:

[quote]true
metodo sobrescrito – FILHO
metodo nao sobrescrito – classe pai
metodo sobrescrito – FILHO[/quote]

achei estranho o comportamento do programa, nas partes que eu comentei o código…
alguém poderia me explicar o porquê dessas coisas?

desde já, agradeço…

Sempre atente ao tipo real do objeto e não da referência.

Apesar de ser uma referência do tipo Pai, o objeto na realidade é do tipo Filho (pai = filho). Sendo assim, a versão que será chamada do método é de Filho e não de Pai.

Na segunda linha, como o método n não foi sobrescrito por filho, ele vai usar a versão herdada de pai (novamente por causa do pai = filho).

Na última, vc fez antes um cast de filho para pai (p = (Pai) filho;)… Esse cast é implícito, pois vc pode atribuir um objeto de uma subclasse a uma referência de superclasse. Os métodos vinculados serão da mesma forma.

Estude sobre polimorfismo e vinculação tardia para mais detalhes.

Até mais!

http://www.guj.com.br/posts/list/49267.java

caramba
tá mais do que explicado, davidbuzatto e mantu, suas respostas vão me dar coisa pra estudar por umas boas horas…

pode considerar o tópico encerrado

edit:
faltou só agradecer: MUITO OBRIGADO :mrgreen:

:wink:

Só complementando.

Em Java o comportamento padrão é diferente do comportamento padrão no C# e no C++.

Em C# e C++ você precisa usar a palavra-chave “virtual”, para que o método chamado dependa do tipo do objeto e não da variável. Se você não usar “virtual”, o método chamado depende do tipo da variável, não do objeto.

O padrão do Java é sempre usar o comportamento “virtual” para tudo que não é “static”. E é por isso que nem existe essa palavra-chave em Java, embora o Java tenha sido inspirado no C++.

Portanto, quem aprende Java sabendo já C# ou C++ acaba se complicando (um pouquinho) porque as coisas são um pouco diferentes.