Есть ли способ получить доступ к другому пакету без публичного модификатора? - PullRequest
2 голосов
/ 06 октября 2009

Допустим, у меня есть пакеты:

com.mycomp.packone
com.mycomp.packtwo

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

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

Ответы [ 4 ]

1 голос
/ 06 октября 2009

Java-пакеты строго ограничены (IMHO) тем, что не существует специального режима для иерархии пакетов и содержания между ними. Каждая упаковка является независимой, и точечная запись предназначена только для человеческих глаз. Возможность ограничения доступа к конкретным клиентам также нарушена (как это иногда заставляет меня хотеть механизм дружбы в C ++ ...)

AFAIK, пока это единственный вариант, пока Java 7, надеюсь, не исправит ситуацию.

Одна вещь, которую вы могли бы рассмотреть, хотя (если ваш проект подходит), это использовать что-то вроде OGSi. Его модульная и экспортная инфраструктура позволяет вам делать вещи, которые более точно настроены, чем позволяет язык.

0 голосов
/ 07 октября 2009

Рассмотрите возможность перепроектирования вашего API, чтобы иметь "внешние" и "внутренние" API.

Хотя вы не можете сделать это с помощью собственных модификаторов доступа Java, вы можете упаковать ваши классы, используя:

package com.mycomp
package com.mycomp.internal

В пакете com.mycomp вы публикуете свои общедоступные API-интерфейсы, от которых вы разрешаете «публичным» пользователям зависеть; в большинстве случаев в этом пакете больше интерфейсов, чем классов.

В пакете

com.mycomp.internal реализовано большинство интерфейсов, имеющихся в com.mycomp . Именование внутреннего пакета эффективно говорит людям, что классы в пакете являются внутренними для API, и выбор зависимости от внутренних пакетов может нарушить их коды в будущих выпусках. Более того, если бы вы могли использовать OSGi, вы можете экспортировать только пакет com.mycomp , что делает com.mycomp.internal эффективно "скрытым" от остального мира.

FWIW, mockito использует этот метод упаковки для своего API.

Недостатком этого метода является зависимость от конвенции.

0 голосов
/ 07 октября 2009

Как сказал Асаф, нарушите правила, используя отражение (используйте метод getDeclaredMethod вместо поля):

package com.mycomp.packone;

public class Introvert {
    protected String secret = "TOP SECRET!";
}

package com.mycomp.packtwo;

import java.lang.reflect.Field;

public class Extrovert {
    public String talk(){
        return this.getSecret();
    }

    @SuppressWarnings("unchecked")
    protected String getSecret(){ // everybody in packtwo can call me!
        try {
            Class introvertClass = Class.forName("com.mycomp.packone.Introvert");
            Object introvert = introvertClass.newInstance();
            Field secretField = introvertClass.getDeclaredField("secret");
            secretField.setAccessible(true);
            return (String) secretField.get(introvert);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } 
    }

    public static void main(String[] args){
        Extrovert extrovert = new Extrovert();
        System.out.println(extrovert.talk());
    }
}
0 голосов
/ 06 октября 2009

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

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