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
}
}
[/code]
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?
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
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.
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.
[quote=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 ;-)[/quote]
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?
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.
[quote=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.
[/quote]
Concordo, eu vacilei aqui… rsrsrrs
[quote=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.[/quote]
Discordo também, se ela foi herdada, é como se ela tivesse sido declarada como atributo da classe Carro.
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:
[code] 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();
}[/code]
para resolver o problema vc pode simplesmente declarar um “int x” na classe Car:
[code] 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();
}[/code]
[quote=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.[/quote]
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.
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.
[code]
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.
}
}[/code]
Obrigado pessoal, isso ajuda a explicar algumas questões perdidas nos mocks.