Частные поля унаследованы подклассом? - PullRequest
9 голосов
/ 16 ноября 2011

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

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.

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

Ответы [ 7 ]

20 голосов
/ 16 ноября 2011

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

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

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

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

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

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

6 голосов
/ 16 ноября 2011

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

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

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

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

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

2 голосов
/ 09 сентября 2013

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

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

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

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

0 голосов
/ 02 декабря 2014

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

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

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

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

0 голосов
/ 18 августа 2013

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

0 голосов
/ 16 ноября 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, и это позволит подклассам изменять его напрямую.Это может быть или не быть желательным во многих обстоятельствах.

0 голосов
/ 16 ноября 2011

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

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

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