Наследуются ли частные поля подклассом?

Я читал, что подкласс не может наследовать частные поля или методы. Однако в этом примере

class SuperClass {
    private int n=3;
    int getN() {
        return n;
    }
}

class SubClass extends SuperClass {
    public static void main(String[] args) {
        SubClass e = new SubClass();
        System.out.println("n= " + e.getN());
    }
}

Когда я запускаю main, я получаю вывод как n=3. Похоже, что SubClass наследует частный атрибут n от SuperClass.

Итак, пожалуйста, объясните, что здесь происходит. Спасибо.


person harish    schedule 16.11.2011    source источник
comment
возможный дубликат Наследуют ли подклассы частные поля?   -  person Stan Kurilin    schedule 27.10.2014


Ответы (7)


Подкласс «имеет» поля своего суперкласса, но не имеет к ним прямого доступа. Точно так же подкласс «имеет» частные методы, но вы не можете вызывать или переопределять их напрямую из подкласса.

В документации Java по наследованию говорится, что

Подкласс не наследует частные члены своего родительского класса.

Тем не менее, я считаю более полезным думать об этом как

Подкласс наследует частные члены своего родительского класса, но не имеет к ним доступа.

но это сводится к семантике.

person Garrett Hall    schedule 16.11.2011
comment
хорошо ... но есть небольшие сомнения, поскольку «подкласс наследует частные члены своего родительского класса, но не имеет к ним доступа», почему мы используем НАСЛЕДОВАНИЕ, в то время как мы можем просто создать экземпляр объекта где-то в том же пакете и можем получить доступ к атрибутам .. - person harish; 16.11.2011
comment
Во многих случаях делегирование (доступ к атрибутам через общедоступные методы) предпочтительнее. Однако для полиморфизма, особенно при использовании Шаблон шаблона, вам нужно создать подкласс (хотя часто лучше использовать интерфейсы). - person Garrett Hall; 16.11.2011

Вы наследуете и используете метод getn(), который является приватным для пакета и доступен из подкласса (поскольку в данном случае оба по своей сути находятся в одном пакете). Вы не можете получить доступ к n напрямую, потому что он приватный. Это метод getn(), который имеет доступ к n, поскольку он находится в том же классе, что и n, а у вас есть доступ к методу getn(), поскольку он не является закрытым.

Если вы сделали:

System.out.println("n= "+e.n+"");

... вместо вашей текущей строки, то она не будет компилироваться по указанной выше причине.

Это совершенно нормальное поведение — выставлять закрытые переменные с помощью методов установки/получения, что, по сути, вы и делаете здесь. Разница в том, что при таком подходе у вас есть возможность проверить/ограничить/изменить/логировать/любое значение переменной, когда вы ее получаете или устанавливаете, и вы можете сделать это, не внося критических изменений при компиляции кода. Вы не сможете сделать то же самое, если просто сделаете поле общедоступным и предоставите людям прямой доступ к нему.

person Michael Berry    schedule 16.11.2011

Это тема, достойная обсуждения. Путаница возникает из-за того, что технически подкласс наследует приватные поля, потому что приватные поля существуют в подклассе, так что когда вы вызываете getN(), он возвращает значение n. Итак, поле n существует в подклассе. Если бы его не было, то при вызове getN() он бы выдал ошибку, так как поля n не существует. Дело в том, что он существует, и, поскольку он был объявлен в суперклассе, технически он был унаследован подклассом.

Однако мы (программисты Java и официальная документация java о наследовании) не рассматриваем это наследование. По нашему соглашению это не считается наследованием, потому что вы не можете напрямую обращаться к значениям этих полей. Это почти как если бы они не были вашими, поскольку единственный способ получить к ним доступ - использовать то, что используют все остальные (классы, которые не являются подклассами этого суперкласса) (геттеры/сеттеры).

Таким образом, концептуально частные поля не наследуются (хотя и существуют в подклассе).

Я думаю, что учителя должны сделать этот момент намного более ясным, чем они. После глубокого взгляда на это, это действительно сбивает с толку.

person Mauro Banze    schedule 09.09.2013

Подкласс может получить доступ к закрытым полям суперкласса только через методы доступа public или protected (геттеры, сеттеры).

Попробуйте получить доступ к частной переменной напрямую и убедитесь, что это не сработает: например.

// won't work
System.out.println("n= "+e.n+"");
person hage    schedule 16.11.2011

Это не скомпилируется:

class NewExample extends Example {
    public static void main (String[] args) {
        NewExample e = new NewExample();
        System.out.println("n=" + e.n);
    }
}

Поскольку переменная объявлена ​​как private, подклассы не имеют к ней прямого доступа. То же, что и с методами. Если вы объявили getn() как private, вы также не сможете получить к нему доступ. Если вы хотите, чтобы подкласс имел прямой доступ к n, вы можете объявить его как protected int n, и это позволит подклассам напрямую изменять его. Это может быть или не быть желательным во многих обстоятельствах.

person Casey    schedule 16.11.2011

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

person score    schedule 18.08.2013

Это отличная тема, которая втянула меня и моего профессора в ссору. Но он доказал свою храбрость, терпеливо объясняя мне.

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

Хотя дочерний класс не может получить доступ к атрибутам или методам, он все равно наследует их!

Каждый язык программирования имеет свою собственную интерпретацию вышеупомянутой концепции наследования и доступности.

person Satz Narayanan    schedule 02.12.2014