Наследование Java - переопределение переменных экземпляра

Почему переменные экземпляра суперкласса не переопределены в наследовании?

Ответ 1

Поскольку наследование предназначено для изменения поведения. Поведение выявляется с помощью методов и почему они могут быть переопределены.

Поля не являются поведением, а состоянием. Вам не нужно изменять это, а также частные методы, используемые суперклассом. Они предназначены, чтобы позволить суперклассу выполнять эту работу.

Ответ 2

Вы можете скрыть поле, но не переопределить.

Скрытие означает, что поле будет иметь другое значение в зависимости от того, к какому классу он обратился. Поле в подклассе "скроет" поле в суперклассе, но оба они существуют.

Это очень плохая практика, чтобы скрыть поле, но работает:

public class HideField {

    public static class A
    {   
        String name = "a";

        public void doIt1() { System.out.println( name ); };
        public void doIt2() { System.out.println( name ); };   
    }

    public static class B extends A
    {
        String name = "b";

        public void doIt2() { System.out.println( name ); };
    }

    public static void main(String[] args)
    {
        A a = new A();
        B b = new B();

        a.doIt1(); // print a
        b.doIt1(); // print a
        a.doIt2(); // print a
        b.doIt2(); // print b <-- B.name hides A.name
    }
}

В зависимости от того, был ли метод overriden, доступ к полю в A или B.

Никогда не делайте этого!. Это никогда не решение вашей проблемы и создает очень тонкие ошибки, связанные с наследованием.

Ответ 3

Потому что:

  • Он может сломать код parent class. Например, рассмотрим следующий код (что будет поведение строки obB.getInt(); в следующем коде, если разрешено переопределение экземпляров):

    class A
    {
        int aInt;
    
        public int getInt()
        {
            return aInt;
        }
    }
    
    class B extends A
    {
        int aInt;
    
        public int getInt2()
        {
            return aInt;
        }
    
        public static void main(String[] args)
        {
             B obB = new B();
    
             //What would be behavior in following line if, 
             //instance variables overriding is allowed
             obB.getInt(); 
        }
    }
    
  • Это не логично, потому что child class должно/отражать все поведение parent class.

Таким образом, вы можете скрыть только унаследованные методы/переменные в child class, но не могут override.

Ниже приведен фрагмент из Java doc из Oracle, определяющий, какую операцию вы можете выполнять/ожидаете от child class:

Вы можете использовать унаследованные элементы как есть, заменить их, скрыть их или дополнить их новыми членами:

  • Унаследованные поля могут использоваться напрямую, как и любые другие поля.
  • Вы можете объявить поле в подклассе с тем же именем, что и в суперклассе, тем самым скрывая его (не рекомендуется).