Question156
Given:
10. public class Foo {
11. public int a;
12. public Foo() { a = 3; }
13. public void addFive() { a += 5; }
14. }
and:
20. public class Bar extends Foo {
21. public int a;
22. public Bar() { a = 8; }
23. public void addFive() { this.a +=5; }
24. }
invoked with:
30. Foo foo = new Bar();
31. foo.addFive();
32. System.out.println(?Value: ?+ foo.a);
What is the result?
A. Value: 3
B. Value: 8
C. Value: 13
D. Compilation fails.
E. The code runs with no output.
F. An exception is thrown at runtime.
Answer: A
Não entendi porque o foo.a esta retornando a variável inteira da superclasse.
Acho que é mais fácil explicar completando seu exemplo.
class Foo {
public int a;
public Foo() { a = 3; }
public void addFive() { a += 5; }
}
class Bar extends Foo {
public int a;
public Bar() { a = 8; }
public void addFive() { this.a +=5; }
}
class Question156 {
public static void main (String[] args) {
Foo foo = new Bar();
foo.addFive();
System.out.println("Value: "+ foo.a); // prints "value: 3"
Bar bar = (Bar) foo;
System.out.println("Value: "+ bar.a); // prints "value: 13"
}
}
A idéia é que só os métodos são sobreescritos, mas não as variáveis, que no máximo podem ser escondidas.
As variáveis de instância se comportam como se fossem métodos estáticos.
Se você entender como é que funcionam os métodos estáticos, vai também entender como funcionam as variáveis de instância.
Quando você criou uma classe Foo, definiu uma variável de instância com o nome “a”.
Quando você criou uma classe Bar, definiu mais uma variável de instância, dessa vez com o nome “a”, que escondeu a outra.
Para acessar a variável de instância “a” da superclasse (Foo), você tem de usar uma referência com o tipo da superclasse.
Para acessar a variável de instância “a” da subclasse (Bar), você tem de usar uma referência com o tipo da subclasse.
o valor é 3, coloque uns System.out.println nos métodos e construtores que você vai entender o que está acontecendo.
quando você faz
significa que você está instanciando um objeto do tipo Foo que se comporta como se fosse um Bar - polimorfismo
a sequencia do que acontece no compilador é:
[quote]- chama o construtor vazio de Foo que inicializa a variavel a com 3
chama o construtor vazio de Bar que inicializa a variavel a com 8
chama o método addFive da classe Bar que atribui para a variavel instancia do objeto do tipo Bar +=5[/quote]
Como o objeto foo é do tipo Foo e não Bar a variável a (variável de instância do objeto Foo) não é incrementada, experimente colocar no método addFive da classe bar assim
a chamada do método estará incrementando a variavel de instancia do pai
posso ter errado em alguns conceitos ou na hora de explicar, por favor me corrigam se estiver errado…
:roll:
Editado: o construtor de Bar inicializa a variavel de instancia a com valor 8
Completei o exemplo com setters e getters.
Como os getters e setters não são escondidos, mas sobreescritos, então o resultado de getA() depende só do tipo da variável.
Então você vai ver que tanto usando “foo.getA()” quanto “bar.getA()” o resultado impresso é sempre 13, já que estamos usando sempre o método “getA” da classe Bar, já que o objeto é da classe Bar.
class Foo {
public int a;
public Foo() { a = 3; }
public void addFive() { a += 5; }
public void setA (int a) { this.a = a; } // note que está usando a variável "Foo.a"
public int getA () { return a; }
}
class Bar extends Foo {
public int a;
public Bar() { a = 8; }
public void addFive() { this.a +=5; }
public void setA (int a) { this.a = a; } // note que está usando a variável "Bar.a"
public int getA () { return a; }
}
class Question156 {
public static void main (String[] args) {
Foo foo = new Bar();
foo.addFive();
System.out.println("Value: "+ foo.a); // prints "value: 3"
Bar bar = (Bar) foo;
System.out.println("Value: "+ bar.a); // prints "value: 13"
System.out.println (foo.getA()); // prints "13"
System.out.println (bar.getA()); // prints "13"
}
}