Java: защищенный доступ через пакеты - PullRequest
14 голосов
/ 22 августа 2010

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

Я знаю, что для классов вне пакета подкласс может видеть защищенный член только через наследование.

Существует два пакета: package1 и package2.

  1. package1: ProtectedClass.java

    package org.test.package1;
    
    public class ProtectedClass {
    
        protected void foo () {
            System.out.println("foo");
        }
    }
    
  2. package2: ExtendsprotectedClass.java

    package org.test.package2;
    
    import org.test.package1.ProtectedClass;
    
    public class ExtendsprotectedClass  extends ProtectedClass {
    
        public void boo() {
            foo(); // This works, 
                   // since protected method is visible through inheritance
        }
    
        public static void main(String[] args) {
            ExtendsprotectedClass epc = new ExtendsprotectedClass();
            epc.foo(); // Why is this working? 
                       // Since it is accessed through a reference,
                       // foo() should not be visible, right?
        }
    }
    
  3. package2: UsesExtendedClass.java

    package org.test.package2;
    
    public class UsesExtendedClass {
    
        public static void main(String[] args) {
            ExtendsprotectedClass epc = new ExtendsprotectedClass();
            epc.foo(); // CompilationError: 
                       // The method foo() from the type ProtectedClass
                       // is not visible
        }
    }
    

Понятно, что метод boo() в ExtendsprotectedClass может обращаться к foo(), поскольку к защищенным элементам можно получить доступ только через наследование.

У меня вопрос: почему метод foo() работает нормально при обращении по ссылке в методе main() из ExtendsprotectedClass, но не будет работать при обращении по ссылке epc в UsesExtendedClass

Ответы [ 4 ]

12 голосов
/ 22 августа 2010

Код в классе ExtendsprotectedClass разрешен для доступа к защищенным членам ProtectedClass через ссылку типа ExtendsprotectedClass.Из раздела JLS 6.6.2 :

Доступ к защищенному члену или конструктору объекта возможен извне пакета, в котором он объявлен только кодом, отвечающим зареализация этого объекта.

и

Пусть C - класс, в котором объявлен защищенный член m.Доступ разрешен только в теле подкласса S из C. Кроме того, если Id обозначает поле экземпляра или метод экземпляра, то:

  • Если доступ осуществляется с помощью квалифицированного имени Q.Id,где Q - ExpressionName, тогда доступ разрешается тогда и только тогда, когда тип выражения Q - S или подкласс S. [...]

UsesExtendedClass isnне несет ответственности за реализацию ExtendsprotectedClass, следовательно, последний вызов не удался.

РЕДАКТИРОВАТЬ: Причина этого заключается в том, что доступ protected разработан, чтобы помочь подклассам реализовать необходимую им функциональность, предоставляя больший доступ квнутренности суперкласса, чем обычно было бы доступно.Если бы это было доступно для всего кода, это было бы довольно близко к обнародованию метода.По сути, подклассам доверяют не нарушать инкапсуляцию;им дается больше возможностей в объектах их собственного типа.Публичный API не должен раскрывать эти детали, но защищенный API может просто дать подклассам больше возможностей.

2 голосов
/ 22 августа 2010

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

1 голос
/ 22 августа 2010

Я думаю, что вы ответили на свой вопрос; UsesExtendedClass не наследуется от ProtectedClass, и, по определению, «защищенные» члены доступны только в классе, в котором они объявлены / определены, или в классе, который наследует от того, в котором они объявлены или определены.

0 голосов
/ 01 мая 2014

посмотрите на эту фотографию: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

enter image description here

ясно, что к защищенному члену класса можно получить доступ через подкласс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...