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

10 respostas
R

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

P

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.

P

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?

R

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?

R

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.

E

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.

R

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.

R

É 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