Наличие двух переменных с одинаковым именем в классе, расширяющем другой класс в Java.

StackOverflow https://stackoverflow.com/questions/772663

Вопрос

Ниже приведена часть моего кода для проекта:

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;
    }
}

Спасибо за ваше время

Это было полезно?

Решение

В некотором смысле вы переопределяете поля суперкласса.Но это гораздо проще сделать случайно, потому что нет перегрузки полей (у вас есть только одна переменная с заданным именем, тип не имеет значения).Это называется «скрытием» или «затенением» переменной.Итак, вы правы, у вас получится два поля с одинаковым именем.

Ваш второй пример верен.Они унаследованы от суперкласса и, поскольку не объявлены частными, они видны подклассу.Как правило, прямая ссылка на поля суперкласса является плохой практикой, и, если нет веской причины, их следует объявить закрытыми.Ваш пример вызова суперконструктора - лучший подход.

Кроме того, если вы скроете одно поле с другим полем с таким же именем, вы все равно сможете ссылаться на него как super.x, super.y, vs.this.x, this.y, вам следует избегать этой ситуации, если это вообще возможно.

Другие советы

Да, у вас будет две переменные, одна из которых скрывает другую.Разрешить это имеет смысл по двум причинам:

  1. Предположим, у вас есть базовый класс Base и производный класс Derived который автор Base понятия не имеет о.Должен ли автор Base никогда не смогу добавлять поля только потому, что производный класс мощь поделитесь полями?Или должен Derived прекратить компиляцию, когда произойдет изменение на Base на корректность не влияет?
  2. Ваши поля почти всегда должны быть закрытыми, и в этот момент не имеет значения, дублируются ли имена или нет — ни одна «сторона» не будет знать о переменных другой.

В дополнение к тому, что сказали другие:Является Body а Point?Нет, Body имеет свойство позиции типа Point.Так Body наверное, не стоит расширять Point.Если вы избавитесь от наследования (от реализации), вы избавитесь от множества проблем.Это и использовать private (нет protected!) и final либерально.

Я быстро понял, что при этом внутри класса Body будут созданы две переменные с именем x и две другие переменные в Body с именем y.Как это вообще возможно и почему Java вообще это допускает?

На самом деле нет, вы не создаете две переменные с одинаковым именем, очевидно, что компилятор не должен и не допустит этого.

Что ты являются это затеняет существующие переменные, определенные как x и y, что означает, что Body.x и Body.y по существу перекрывают имена Point.x и Point.y, что делает последние две переменные полностью недоступными из класса Body (ссылка на определение «затенения» в спецификации языка Java).

Скрытие имен обычно воспринимается как плохая практика и причина ошибок, и если вы включите предупреждения компилятора javac, компилятор послушно предупредит вас об этом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top