O seguinte codigo imprime 40 para tal eu cheguei a conclusão que o construtor da superclasse está chamando um metodo sobrecarregando na subclasse.
public class Base {
int value = 0;
Base(){
addValue();
}
public void addValue(){
System.out.println("To sendo chamado na classe base");
value += 10; }
int getValue(){
return value;
}
}
class Derived extends Base{
Derived(){addValue();}
public void addValue() {
System.out.println("To sendo chamado na classe Derived");
value+=20;
}
}
public class Teste {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Base b = new Derived();
System.out.println(b.getValue());
}
}
Ao instanciar objeto “d” (Derived) seu construtor chama primeiro o construtor da superclasse Base, implicitamente (super()), que vai invocar o método “addValue()” que foi sobrescrito na subclasse, fazendo “value” valer 20, após isso é executado o construtor da subclasse Derived, q adiciona mais 20 ao “value”, resultando em 40.
Portanto, o método “addValue()” foi sobrescrito e não sobrecarregado, pois se fosse sobrecarregado, como a referência de “b” foi feita para a superclasse Base, o método “addValue” da subclasse não seria exergado qd fosse invocado.
Eu entendi que se trata sobreescrição.
O que eu não entendi é por que quando o construtor da superclasse e executado e chamado a versão sobeescrita do metodo??
Obrigado.
Essa é a grande vantagem da sobrescrita. Você poder redefinir o método. Imagina que o método na superclasse fosse abstrato, o que aconteceria se ele fosse invocado e a superclasse não pudesse ver o método sobrescrito?
Sobrescrever significa “esqueça a implementação da superclasse e use isto no lugar”.
Cara, isso é muito fácil de confundir! Muito bom exemplo!
Na primeira vez q eu vi parecia-me que vc estava chamando b.addValue() e não b.getValue(). Mesmo acessando o contrutos da superclasse ele ainda usa o método sobreescrito. Então instanciando uma variável da subclasse o método da superclasse não será útil mais. Mesmo qd foi chamado dentro do construtor da superclasse.
Mas… olha só o que eu fiz tentando estudar um pouco mais o código
class Base {
int value = 0;
Base(){
addValue();
}
private void addValue(){
System.out.println("To sendo chamado na classe base");
value += 10;
}
int getValue(){
return value;
}
}
class Derived extends Base{
Derived(){
addValue();
}
public void addValue() {
System.out.println("To sendo chamado na classe Derived");
value+=20;
}
}
public class DerivedTest00 {
public static void main(String[] args) {
Base b = new Derived();
System.out.println(b.getValue());
}
}
Coloquei o método da superClasse como private. Resultado… o código compila, porém o método addValue não é sobreescrito, então o primeiro contrutor que roda, o da classe Base é obrigado a chamar o método addValue da classe Base e depois o segundo contrutor que roda, da classe Derived chama o método addValue() da classe Derived.
Resultado:
To sendo chamado na classe base
To sendo chamado na classe Derived
30
Apesar que isso possa ser fácil de confundir, ele pode ser um grande aliado no dia a dia. Dê uma pesquisada sobre Template methods pattern e você vai entender melhor essa parte de sobreescrita e como ela pode te ajudar no dia a dia.
Jamais chame métodos sobrescritos no construtor da classe.
Lembrem-se que a construção ocorre de cima para baixo, portanto, você estará chamando um método de um trecho da classe que sequer foi construído ainda.
O comportamento disso é completamenteindefinido. E, mesmo onde não der erro, será inconsistente também.