Ter 2 variáveis com o mesmo nome em uma classe que estende outra classe em Java
Pergunta
A seguir está uma parte do meu código para um projeto:
public class Body extends Point{
public double x, y, mass;
public Body() {
x = y = mass = 0;
}
public Body(double x, double y, double mass) {
this.mass = mass;
this.x = x;
this.y = y;
}
}
public class Point {
public double x;
public double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
Eu rapidamente percebi que fazer isso criaria dois variáveis dentro da classe Body chamadas x e duas outras variáveis em Body chamadas y.Como isso é possível e por que diabos o Java permite isso?
Presumo que este seja o código correto da classe Body:
public class Body extends Point{
public double mass;
public Body() {
super();
mass = 0;
}
public Body(double x, double y, double mass) {
super(x,y);
this.mass = mass;
}
}
Obrigado pelo seu tempo
Solução
De certa forma, você está substituindo os campos da superclasse.Mas é muito mais fácil fazer isso acidentalmente porque não há sobrecarga de campos (você só tem uma variável com um determinado nome, o tipo não importa).Isso é conhecido como 'ocultação' ou 'sombreamento' de variável.Então, você está correto, você terá dois campos com o mesmo nome.
Seu segundo exemplo está correto.Eles são herdados da superclasse e, como não são declarados privados, são visíveis para a subclasse.Geralmente é uma má prática referir-se diretamente aos campos de uma superclasse e, a menos que haja um bom motivo, eles devem ser declarados privados.Seu exemplo de invocação do superconstrutor é a melhor abordagem.
Além disso, se você ocultar um campo com outro com o mesmo nome, ainda poderá referir-se a eles como super.x, super.y, vs.this.x, this.y, você deve evitar esta situação se possível.
Outras dicas
Sim, você terá duas variáveis, uma ocultando a outra.Faz sentido permitir isso por dois motivos:
- Suponha que você tenha uma classe base
Base
e uma classe derivadaDerived
qual o autor deBase
não tem ideia sobre.Caso o autor deBase
nunca será possível adicionar nenhum campo, só porque uma classe derivada poder compartilhar os campos?Ou deveriaDerived
pare de compilar quando a mudança paraBase
na verdade não afeta a correção? - Seus campos quase sempre devem ser privados, e nesse ponto não importa se os nomes estão duplicados ou não - nenhum dos "lados" saberá sobre as variáveis do outro.
Além do que outros disseram:É Body
a Point
?Não, Body
tem uma propriedade de posição do tipo Point
.Então Body
provavelmente não deveria estender Point
.Se você se livrar da herança (de implementação), você se livrará de muitos problemas.Isso e usar private
(não protected
!) e final
liberalmente.
Rapidamente percebi que fazer isso criaria duas variáveis dentro da classe Body chamadas x e duas outras variáveis em Body chamadas y.Como isso é possível e por que diabos o Java permite isso?
Na verdade não, você não está criando duas variáveis com o mesmo nome, obviamente um compilador não deveria e não permitiria isso.
O que você são fazer é sombrear as variáveis existentes definidas como x
e y
, o que significa que Body.x e Body.y estão essencialmente sobrepondo os nomes de Point.x e Point.y, tornando as duas últimas variáveis completamente inacessíveis da classe Body (link para a definição de "sombreamento" da Especificação da Linguagem Java).
O sombreamento de nomes geralmente é considerado uma prática ruim e uma causa de bugs, e se você ativar os avisos do compilador javac, o compilador irá avisá-lo respeitosamente sobre isso.