Java: невозможно получить доступ к защищенным методам вложенного класса в подклассе внешнего класса - PullRequest
0 голосов
/ 18 февраля 2019

Я разлагаю класс для повторного использования, различных реализаций, скрытых информацией и т. Д.

Это было:

public class Outer
{
    public static class Inner
    {
        // ...
        protected static void innerDoSomething()
        {
            // ...
        }
    }

    public outerDoSomething()
    {
        //...   
        Inner.innerDoSomething();
        //...
    }
}

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

Но попытка разложения таким образом:

public class SuperOuter
{
    public static class SuperInner
    {
        // ...
        protected static void innerDoSomething()
        {
            // ...
        }
    }

    // ...
}

public class SubOuter extends SuperOuter
{
    public static class SubInner extends SuperInner
    {
        // ...
        protected static void innerDoSomethingElse()
        {
            // ...
        }
    }

    public outerDoSomething()
    {
        //...   
        SubInner.innerDoSomethingElse(); // OK
        SubInner.innerDoSomething();     // Error: cannnot access!
        //...
    }
}

innerDoSomething () недоступна, даже если защищенные члены SubInner доступны черезSubOuter и все защищенные члены SuperInner должны быть частью защищенного интерфейса SubInner.

Единственный способ заставить его работать, кажется, добавить явное делегирование для каждого метода, например:

    public static class SubInner extends SuperInner
    {
        // ...
        protected static void innerDoSomethingElse()
        {
            // ...
        }

        protected static void innerDoSomething()
        {
            SuperInner.innerDoSomething();
        }
    }

Что раздражает, подвержено ошибкам и тратит время.Я испытываю желание просто объявить innerDoSomething () как public, но это не совсем правильно, поскольку он предназначен для использования только SubOuter и его подклассами.

Почему?Разве не должен быть разрешен внутренний доступ к защищенному доступу innerDoSomething () и доступ с помощью SubOuter?

Ответы [ 2 ]

0 голосов
/ 12 марта 2019

Ладно, думаю, я справился, внимательно перечитав Гослинг Язык программирования Java, 4-е изд. :

  1. SuperOuter и SubOuter находятся в разных пакетах, как они должны быть логически, так что нет общего целого пакета доступность защищенных членов на месте.

  2. Доступ к защищенному члену вложенного класса фактически предназначенный как специальное средство доступа между внешними и вложенными классами (см. Глава 5. Вложенные классы и интерфейсы )

  3. Все же, защищенная доступность членов не просто транзитивен : кроме вложенной формы / внешнего гранта, вы должны оба быть в подклассе и иметь ссылку, которая по крайней мере соответствует типу этого подкласса (т.е. по крайней мереSubXXX, SuperXXX недостаточно), потому что я цитирую пункт 3.5.Что защищает Really Means :

Каждый подкласс наследует контракт суперкласса и каким-то образом расширяет этот контракт.Предположим, что один подкласс, как часть его расширенного контракта, накладывает ограничения на значения защищенных членов суперкласса.Если другой подкласс может получить доступ к защищенным членам объектов первого подкласса, он может манипулировать ими таким образом, что нарушит контракт первого подкласса, и это не должно быть допустимым.

Так что, даже еслив моем случае xxxInner логически должен быть частью xxxOuter, а SubOuter расширяет SuperOuter, поэтому первый логически должен иметь возможность доступа к любым защищенным элементам последнего, однако SubOuter не может получить доступ к защищенным элементам SuperInner в SuperOuter точно так же, как онневозможно, если бы он получил SuperInner в качестве аргумента параметра, , потому что этот аргумент мог принадлежать совершенно другому разветвлению иерархии .В этом случае нет конкретного положения в языке для установления соединения.

Это также объясняет, почему работает явное делегирование: SubOuter имеет доступ к защищенным членам SubInner, потому что внешний / вложенный грант, а SubInner имеет доступ к защищенномучлены SuperInner из-за расширения, но SubOuter не может получить доступ к защищенным членам SuperInner, потому что последний может фактически принадлежать к другому разветвлению иерархии, и это задача SubInner, чтобы установить соединение , так сказать.

Явное делегирование учитывает все вышеперечисленное, логически и по языковым определениям, поэтому это должен быть «правильный» путь, учитывая правильный доступ, но он подвержен ошибкам в реализации из-за избыточности (что если я вызову SuperInner.innerDoSomethingElse() внутри SubInner.innerDoSomething ()?)

В конечном счете: я мог бы автоматизировать явное делегирование, например, с помощью некоторых сценариев Python (я сделал для автоматизации создания шаблонов Builder, которыеиметь аналогичный недостаток избыточности) или просто отказаться от дополнительной безопасности контроля доступа и сделать защищенных членов публичными.

0 голосов
/ 18 февраля 2019

Защищенный метод не может быть доступен из другого пакета через ссылку на переменную.Это будет работать, если два класса SuperOuter и SubOuter будут находиться в одном пакете.

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