Dúvida questão

Bom dia, fazendo o TestKiller me deparei com essa questão:

class Foo {
	public int a;
	public Foo() { a = 3; }
	public void addFive() { a += 5; }
}

public class Bar extends Foo {

    	public int a;
    	public Bar() { a = 8; }
    	public void addFive() { this.a +=5; }
    	

    	public static void main( String[] args ) {
    		Foo foo = new Bar();
    		foo.addFive();
    		System.out.println("Value: " + foo.a);
    	}
}

e as alternativas:
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.

A resposta correta é a letra a, Value: 3

Posso estar sendo cego e ser óbvio o pq disso, mas não estou entendendo, será que alguem poderia me explicar essa questão?

Abraços.

Acho que a resposta está no detalhe do método addFive de Bar:

Então ele muda o valor do atributo a de Bar e quando ele exibe, ele exibe o de Foo, porque foo é do tipo Foo.
Acho que é por isso.

Hmmmmm tem razão cara…

ele chama o addFive de Bar… e na hora da chamada ele chama a variável de Foo que tá lá apenas inicializado com o valor 3…

Poxa, muito obrigado, agora entendi…

Certificação é cheio de pegadinha…
A prova nem avalia muito o conhecimento, pois tem várias questões decorebas e muitas com questões sem sentido…

onde acho este simulado TestKiller?

ele não deveria dar erro ??? pq o atributo a nao esta em duplicidade ???

Cara eu baixei ele no 4shared…

Tipo, eu implementei o exemplo e realmente dá a saída 3. Então pelo que eu entendi ele faz sombreamento, não sei se estou certo…

Abraço.

Por acaso este TestKiller é em pdf?? Baixei alguma coisa aqui, mas era em PDF, não sei se é o correto.

Se fosse eu, teria respondido a letra C, 13. E teria errado :shock:

[quote]Por acaso este TestKiller é em pdf?? Baixei alguma coisa aqui, mas era em PDF, não sei se é o correto.

Se fosse eu, teria respondido a letra C, 13. E teria errado [/quote]

Sim cara, é em .pdf

Poxa, eu respondi a B hehe

hmm … q estranho … e o modificador de visibilidade … ambos são public …

entao quando faço this.a eu chamo o da classe Foo … e qnd faço foo.a … eu chamo o da classe mae … deve ser isso !!!

agor aestou na duvida … vou pesquisar melhor sobre isso

vlwww

Justamente, quando você utiliza a palavra this você está explicitando que quer utilizar algo daquela referência, da atual referência.

Mas mesmo se a gente tirar o this ele vai usar o atributo de Bar… só se a gente colocasse o super.a que ele chamaria o da super classe ali… só me responde… isso é sombreamento??

Abraços.

SIm.
é sombreamento.

Eu não consegui compreender ainda o porque desta resposta. Quando chegar em casa a noite vou recorrer ao livro da Kathy para ver se encontro algo que justitique esta resposta e também vou analisar esta questão novamente.

Mas, por enquanto, ainda continuo achando que seria 13.

Alguém que compreendeu bem, poderia fazer um passo-a-passo aí da execução do programa, com explicação 8) .
Senão depois faço um debug.

Tipo cara… pelo que eu entendi é o seguinte:

class Foo {
	public int a;
	public Foo() { a = 3; }
	public void addFive() { a += 5; }
}

public class Bar extends Foo {

    	public int a;
    	public Bar() { a = 8; }
    	public void addFive() { this.a +=5; }
    	

    	public static void main( String[] args ) {
    		Foo foo = new Bar();
    		foo.addFive();
    		System.out.println("Value: " + foo.a);
    	}
}

Na chamada a Foo foo = new Bar(); ele chama o construtor de Bar que chama o de Foo… nisso temos duas variáveis de instância Foo.a e Bar.a

Foo.a = 3 e Bar.a = 8

então ele chama foo.addFive() e é chamado o método de Bar que está devidamente sobrescrito, o que deixa Bar.a = 13 como você mesmo disse…

E então temos a chamada a foo.a que chama a variável de Foo que é o tipo da instância Foo foo, cujo valor é foo.a = 3 já que a variável a de Foo foi apenas inicializada com o valor 3… depois não fizemos outras alterações nela, apenas na variável de Bar;

Ola!

Os atributos não são subscritos, no caso do atributo “a”.

Qdo foi inicializado o Bar automaticamente foi feita a chamada do construtor super que é o Foo e então foi atribuido o valor 3 para o atributo “a”. E no System.out.println("Value: " + foo.a); ele vai chamar o atributo correspondente ao Foo e nao ao Bar.

depois de testar esse codigo, compreendi pq o resultado foi 3 :smiley:
a sacada desse exercicio está no método addFive() que tenta fazer a pegadinha…

Cara a regra é a seguinte: A herança existe apenas para metodos desde que nao sejam estaticos, ou seja, voce nao pode sobrescrever uma variavel de instantia. Quando voce declarou int a ; na classe Foo e int a; na classe Bar, cada uma é independente de si. Quando vc intanciou, da seguinte forma :

Foo foo = new Bar(); voce esta utilizando uma referencia Foo, porem um objeto do tipo Bar. Nesta hora o objeto foo nao encherga a variavel “a” declarada na classe Bar. É como voce se declarasse um metodo na classe filha que nao existe na classe pai, sendo assim o objeto foo tambem nao enxergará esse metodo novo. Na hora da compilaçao o contrutor da classe Bar chama o construtor da classe Foo atribuindo o valor 3 a variavel a da classe Foo. Como na herança, tudo que estiver na classe pai é herdada pela filha, caso esteja marcada com os modificadores corretos. Por isso foo.a é mostrado com o valor 3.

Espero ter ajudado… Bons estudos para voce…

o detalhe ai é que o objeto de fato é Bar, então ele vai chamar seu próprio método devido a subscrita do método.