Java: доступ к подклассу без доступа к пакету

Довольно новичок в Java, но мне интересно, почему доступ к пакету считается «более ограничительным», чем доступ к подклассу. То есть каждый модификатор доступа, который предоставляет подклассам доступ к члену, также предоставляет доступ ко всему пакету, и есть модификаторы, которые предоставляют доступ к пакету, но не доступ к подклассу.

Разве это не совсем назад? Допустим, у меня есть класс ControlledInstantiation в каком-то пакете. Если у меня есть другой класс. И если я установлю для него значение protected, теперь любой другой класс в пакете сможет создавать его экземпляры столько раз, сколько захочет. Таким образом, то, что обязано быть взаимозаменяемым для своего суперкласса (и синтаксически таковым и является), получает такой же или меньший доступ к суперклассу, чем то, что выполняет отдельную, но родственную функцию. Это все равно, что сказать ребенку, что он не может играть с вашим кошельком, потому что вы не позволите делать это соседям, а затем позволить вашим соседям спать в вашем доме, потому что это делает ваш ребенок.

Итак, я думаю, я спрашиваю, что мотивировало это решение и как я могу его обойти?


person Innominate    schedule 21.11.2010    source источник
comment
но вы пишете код для ControlledInstantiation и, следовательно, предположительно являетесь владельцем кода в его пакете .. вы говорите, что не доверяете себе?   -  person pstanton    schedule 21.11.2010
comment
Любой может создать новый класс в любом пакете, кроме тех, которые защищает загрузчик классов. Если только я не скрою имя пакета внутренне используемого класса во всех моих задокументированных интерфейсах (что, я думаю, невозможно, поскольку даже фабрика должна импортировать созданный ею класс, и в какой-то момент нужно ссылаться на саму фабрику и т. д. .), любой может поместить класс в этот пакет. Люди почти наверняка не стали бы этого делать, если бы не хотели сделать что-то, чего им делать не следует, но они могли бы.   -  person Innominate    schedule 21.11.2010


Ответы (3)


На первый взгляд это может показаться обратным, но идея состоит в том, что пакет Java должен содержать набор сравнительно связанных классов, которые семантически связаны, и это отражено в модификаторе пакета по умолчанию. Тогда логика такова, что если вы хотите сделать еще один шаг и разрешить подклассам из любого пакета просматривать ваши члены, вы можете объявить их защищенными. Есть ли для вас смысл в том, что подклассам из сторонних пакетов следует доверять меньше, чем любому классу (будь то подкласс или нет) из вашего собственного пакета?

На самом деле в Java когда-то был модификатор private protected, который достигал того, что вам нужно, но я полагаю, что он был удален, потому что это сбивало людей с толку. Я не совсем уверен, как вы могли бы добиться этого, не переводя каждую пару классов/подклассов в отдельный пакет. Но это запутанное решение, которое идет вразрез с принципами Java, и в любом случае оно не будет работать для иерархий наследования, состоящих более чем из двух классов.

person Nathan Pitman    schedule 21.11.2010

Вы правы, этот факт немного сбивает с толку. Вот обходные пути, которые я могу предложить.

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

  2. Если вы действительно хотите избежать доступа к защищенному методу членами пакета, вы можете решить эту проблему, по крайней мере, во время выполнения, используя Throwable.getStacktrace():

    if(!getClass().isAssignableFrom(
        Class.forName(new Throwable().getStackTrace()[1].getClassName()))) {
            throw new IllegalAccessException(
                "This method can be accessed by subclass only");
    }
    
person AlexR    schedule 21.11.2010
comment
ваши ответы хороши, но, пожалуйста, научитесь правильно форматировать примеры кода: stackoverflow.com/editing-help - person Sean Patrick Floyd; 21.11.2010
comment
Извините за плохое форматирование. Обычно я так и делаю, но на этот раз я несколько раз пытался отформатировать его, и это просто не сработало! - person AlexR; 21.11.2010

Вы можете запечатать пакет. См. Спецификацию файла JAR.

person user207421    schedule 21.11.2010