Dúvida ao chamar super.metodo(). [RESOLVIDO]

10 respostas
rmala_ti

Boa noite.

Surgiu uma dúvida nesse código ai:

class Veiculo{
	int x = 10; 

	public void metodo() {
		System.out.println("Valor de x em Veiculo: " + x); //Imprime 10 - OK
	}
}

class Carro extends Veiculo{
	
	public void metodo(){
		x = 11; // variável herdada, não altera a variável de instância de Veiculo

		System.out.println("Valor de x em Carro: " + x); // Imprime 11 - OK

		super.metodo(); //Estranhamente imprime 11 ao invés de 10, pq??
		
        new Veiculo().metodo(); //Aqui imprime 10 corretamente
	}
}

A dúvida é com relação a variável de instância x herdada.
Qual o motivo de a chamada super.metodo() imprimir 11, já que ela chama o método da super classe?

Grato.

10 Respostas

peczenyj

Quando vc fez x=10 na classe pai vc criou um atributo de visibilidade ‘padrão’.
A classe filha alterou o valor do atributo herdado da classe pai. Quando vc executou super.metodo vc invocou o codigo original. O que o codigo original faz? acessa this.x que, nesse objeto, vale 11.

Quer ver prevalecer o valor da classe pai? Faça x= 10 ser private.

Acho que vc esta confundindo com o contexto estatico também. Vc não esta acessando um estado na classe pai pois este estado não existe mais :wink:

T

Quando vc fez a atribuição x = 11 na classe Carro, a variável alterada foi na verdade a da classe Veículo (pois a classe carro não possui uma variável x). Logo após, quando vc faz super.metodo() vc está chamando o método da classe veículo que usa a mesma variável x que vc acabou de alterar.

Na linha de baixo ( new Veiculo().metodo(); ) vc está criando um novo objeto. E esse novo objeto possui o valor de x = 10 normal (vc não alterou ele). Por isso que ao chamar o método “metodo()” dele ele imprime 10.

O fato de uma classe A herdar uma variável de instância da classe B não implica que a classe A irá ter uma cópia da variável. Ela ira usar a mesma variável da classe B.

peczenyj

O termo correto seriam atributos. Gosto de pensar em variaveis como algo que eu crio no escopo de um método (ou bloco de codigo) que ira desaparecer com o termino do mesmo. Pensar em variaveis nesse caso é pensar que podem existir contextos globais como em outras linguagens.

T

Mas variáveis de instância não é a mesma coisa que atributos?

rmala_ti

peczenyj:
Quando vc fez x=10 na classe pai vc criou um atributo de visibilidade ‘padrão’.
A classe filha alterou o valor do atributo herdado da classe pai. Quando vc executou super.metodo vc invocou o codigo original. O que o codigo original faz? acessa this.x que, nesse objeto, vale 11.

Quer ver prevalecer o valor da classe pai? Faça x= 10 ser private.

Acho que vc esta confundindo com o contexto estatico também. Vc não esta acessando um estado na classe pai pois este estado não existe mais ;-)

Então o fato de imprimir 11 é simplesmente devido a chamada this.x no método padrão, e this neste contexto se refere ao objeto da classe Carro, é isso?

rmala_ti

Tiago, eu discordo.
A variável x é defaul então ela é herdada sim pela subclasse e a variável alterada em Carro é a que essa classe herdou.

TiagoTC:
Na linha de baixo ( new Veiculo().metodo(); ) vc está criando um novo objeto. E esse novo objeto possui o valor de x = 10 normal (vc não alterou ele). Por isso que ao chamar o método “metodo()” dele ele imprime 10.

Concordo, eu vacilei aqui… rsrsrrs

TiagoTC:

O fato de uma classe A herdar uma variável de instância da classe B não implica que a classe A irá ter uma cópia da variável. Ela ira usar a mesma variável da classe B.

Discordo também, se ela foi herdada, é como se ela tivesse sido declarada como atributo da classe Carro.

evertonsilvagomesjav

cara vc esta alterando valor de uma variavel herdada ou seja no objeto que vc esta usando pra chamar o método vc esta realmente alterando o valor dela em Veiculo sim faça o teste com this.x que fica mais facil de enchergar:

public void metodo(){  
	
		this.x = 11;
//aqui seria o equivalente a: c.x = 11; ok?   
	    System.out.println("Valor de x em Carro: " + x); 
		   
	    super.metodo();
		           
	    new Veiculo().metodo(); 
   }

	 
	public static void main(String[] args) {
		
		Car c = new Car();

		c.metodo();
	}

para resolver o problema vc pode simplesmente declarar um "int x" na classe Car:

public void metodo(){  
	
	int x = 100; // ou qualquer outro numero que vc quiser

	    System.out.println("Valor de x em Carro: " + x); 
		   
	    super.metodo();
		           
	    new Veiculo().metodo(); 
   }

	 
	public static void main(String[] args) {
		
		Car c = new Car();

		c.metodo();
	}
T

TiagoTC:

O fato de uma classe A herdar uma variável de instância da classe B não implica que a classe A irá ter uma cópia da variável. Ela ira usar a mesma variável da classe B.

Discordo também, se ela foi herdada, é como se ela tivesse sido declarada como atributo da classe Carro.[/quote]

Como assim rmalati? Não existe isso de “redeclaração implícita”. A única forma de a classe Carro ter um atributo próprio é declarando ela explicitamente com int x (colocando o tipo antes, conforme o everton explicou). O que acontece é o seguinte: o método “metodo()” da classe Carro possui a atribuição x = 11. Primeiro ele vai procurar no escopo daquele método a variável x. Como não tem nenhuma declaração, ele vai para o escopo da classe Carro. Como também não tem nenhum atributo x declarado na classe Carro, ele então vai procurar nos atributos da classe que Carro herdou (no caso Veículo). Como Veículo possui x declarado, ele vai usar esse. Mas ele não copia o valor de x ou algo parecido. Ele vai usar exatamente esse x da classe Veículo.

rmala_ti

Pouts... num acredito...
agora finalmente eu entendi isso....

Estava enganado mesmo, mas agora clareou.
Eu tinha entendido que se uma classe um membro é como se esta classe tivesse declarado ela mesma.
Herda mesmo, mas existe somente uma variável, a que foi declarada na super classe.

public class Sobrescricaoteste3 {
  public static void main(String [] args){
	  new Sub().teste();
  }
}

class Super{
	int x = 222;
	public void teste(){
		System.out.println("Valor de x em Super = " + this.x);
	}
}


class Sub extends Super{
	int x = 22;
	public void teste(){
		this.x = 444;
		System.out.println("Valor de x em Sub = " + this.x); // 444
		super.teste(); //222 considerando que Sub declara x, se não declarar imprimirá 444 mesmo.
	}
}

Obrigado pessoal, isso ajuda a explicar algumas questões perdidas nos mocks.

rmala_ti

É Tiago eu achava que era uma redeclaração implícita mesmo, valeu pela ajuda ai.

Criado 26 de janeiro de 2010
Ultima resposta 26 de jan. de 2010
Respostas 10
Participantes 4