Имея 2 переменные с тем же именем в классе, который расширяет другой класс в Java
Ниже приведена часть моего кода для проекта:
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;
}
}
Я быстро понял, что при этом создаются переменные два внутри класса Body, называемого x, и две другие переменные в Body, называемые y. Как это возможно, и почему на самом деле Java даже разрешает это?
Я предполагаю, что это правильный код класса 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;
}
}
Спасибо за ваше время
Ответы
Ответ 1
В некотором смысле вы являетесь основными полями суперкласса. Но это намного проще сделать случайно, потому что нет перегрузки полей (у вас есть только одна переменная с заданным именем, тип не имеет значения). Это называется переменной "скрытие" или "затенение". Итак, вы правы, вы получите два поля с тем же именем.
Ваш второй пример правильный. Они наследуются от суперкласса и, поскольку они не объявлены частными, они видны подклассу. Как правило, неверная практика относится непосредственно к полям суперкласса, и если нет веских оснований, они должны быть объявлены частными. Ваш пример вызова супер-конструктора - лучший подход.
Кроме того, если вы спрячете поле с другим именем, вы все равно можете ссылаться на них как super.x, super.y, vs. this.x, this.y, вам следует избегать этой ситуации, если вообще возможное.
Ответ 2
Да, у вас будет две переменные, одна из которых скрывает другую. Имеет смысл разрешить это по двум причинам:
- Предположим, у вас есть базовый класс
Base
и производный класс Derived
, о котором автор понятия Base
понятия не имеет. Если автор Base
никогда не сможет добавлять какие-либо поля, просто потому, что производный класс может делиться полями? Или следует Derived
прекратить компиляцию, когда изменение на Base
не влияет на правильность?
- Ваши поля должны быть почти всегда закрытыми, и в этот момент не имеет значения, дублируются ли имена или нет - ни одна из сторон не будет знать о переменных других.
Ответ 3
В дополнение к тому, что говорили другие: Is Body
a Point
? Нет, Body
имеет свойство position типа Point
. Поэтому Body
, вероятно, не следует расширять Point
. Если вы избавитесь от наследования (реализации), вы избавитесь от множества проблем. Это и используйте private
(не protected
!) И final
либерально.
Ответ 4
Я быстро понял, что это создаст две переменные внутри класса Body, называемые x, и две другие переменные в Body, называемые y. Как это возможно, и почему на самом деле Java даже разрешает это?
На самом деле нет, вы не создаете две переменные с тем же именем, очевидно, компилятор не должен и не допускал этого.
То, что вы делаете, это затенение существующих переменных, определенных как x
и y
, что означает, что Body.x и Body.y по существу перекрывают имена Point.x и Point.y, что делает последние две переменные полностью недоступный из класса Body (ссылка на определение языка Java "shadowing" ).
Затенение имен обычно воспринимается как плохая практика и причина ошибок, и если вы включите предупреждения компилятора javac, компилятор будет с вами об этом предупреждать.