Większość odpowiedzi stwierdzała, że w Javie nie ma czegoś takiego jak podpakiet, ale nie jest to do końca dokładne. Termin ten znajdował się w specyfikacji języka Java już w Javie 6 i prawdopodobnie później (nie wydaje się, aby istniała swobodnie dostępna wersja JLS dla wcześniejszych wersji Java). Język wokół podpakietów nie zmienił się zbytnio w JLS od czasu Java 6.
Składowymi pakietu są jego podpakiety oraz wszystkie typy klas najwyższego poziomu i typy interfejsów najwyższego poziomu zadeklarowane we wszystkich jednostkach kompilacji pakietu.
Na przykład w Java SE Platform API:
- Pakiet
java
ma podpakietów awt
, applet
, io
, lang
, net
, i util
jednostki, ale nie kompilacji.
- Pakiet
java.awt
ma nazwany podpakiet image
, a także kilka jednostek kompilacji zawierających deklaracje typów klas i interfejsów.
Koncepcja podpakietu jest istotna, ponieważ wymusza ograniczenia nazewnictwa między pakietami i klasami / interfejsami:
Pakiet nie może zawierać dwóch elementów członkowskich o tej samej nazwie lub może wystąpić błąd w czasie kompilacji.
Oto kilka przykładów:
- Ponieważ pakiet
java.awt
zawiera podpakiet image
, nie może (i nie zawiera) deklaracji klasy lub typu interfejsu o nazwie image
.
- Jeśli w pakiecie znajduje się pakiet o nazwie
mouse
i typ elementu członkowskiego Button
(który następnie może być określany jako mouse.Button
), nie może istnieć żaden pakiet o w pełni kwalifikowanej nazwie mouse.Button
lub mouse.Button.Click
.
- Jeśli
com.nighthacks.java.jag
jest w pełni kwalifikowaną nazwą typu, nie może istnieć żaden pakiet, którego w pełni kwalifikowaną nazwą jest albo com.nighthacks.java.jag
lub com.nighthacks.java.jag.scrabble
.
Jednak to ograniczenie nazewnictwa jest jedynym znaczeniem, jakie język nadaje podpakietom:
Hierarchiczna struktura nazewnictwa paczek ma być wygodna do organizowania powiązanych paczek w konwencjonalny sposób, ale sama w sobie nie ma żadnego znaczenia poza zakazem dotyczącym paczki mającej podpakiet o tej samej nazwie prostej, co typ najwyższego poziomu zadeklarowany w tym pakiecie .
Na przykład nie ma specjalnej relacji dostępu między pakietem o nazwie oliver
a innym pakietem o nazwie oliver.twist
lub między pakietami o nazwie evelyn.wood
i evelyn.waugh
. Oznacza to, że kod w pakiecie o nazwie oliver.twist
nie ma lepszego dostępu do typów zadeklarowanych w pakiecie oliver
niż kod w jakimkolwiek innym pakiecie.
W tym kontekście możemy odpowiedzieć na samo pytanie. Ponieważ wyraźnie nie ma specjalnej relacji dostępu między pakietem a jego podpakietem lub między dwoma różnymi podpakietami pakietu nadrzędnego, w języku nie ma możliwości, aby metoda była widoczna dla dwóch różnych pakietów w żądany sposób. Jest to udokumentowana, celowa decyzja projektowa.
Albo metodę można upublicznić, a wszystkie pakiety (w tym odp.proj
i odp.proj.test
) będą mogły uzyskać dostęp do podanych metod, albo metoda może zostać ustawiona jako prywatna (domyślna widoczność), a cały kod, który musi uzyskać bezpośredni dostęp, musi zostać umieszczony ten sam (pod) pakiet co metoda.
To powiedziawszy, bardzo standardową praktyką w Javie jest umieszczanie kodu testowego w tym samym pakiecie co kod źródłowy, ale w innym miejscu w systemie plików. Na przykład w narzędziu do kompilacji Maven konwencja będzie taka, aby umieścić te pliki źródłowe i testowe odpowiednio w src/main/java/odp/proj
i
src/test/java/odp/proj
. Kiedy narzędzie kompilacji to kompiluje, oba zestawy plików trafiają do odp.proj
pakietu, ale tylko te src
pliki są uwzględniane w artefakcie produkcyjnym; pliki testowe są używane tylko w czasie kompilacji do weryfikacji plików produkcyjnych. Dzięki tej konfiguracji kod testowy może swobodnie uzyskiwać dostęp do dowolnego kodu prywatnego lub chronionego kodu testowanego kodu, ponieważ będą one znajdować się w tym samym pakiecie.
W przypadku, gdy chcesz udostępniać kod między podpakietami lub pakietami rodzeńskimi, które nie są przypadkiem testowym / produkcyjnym, jednym z rozwiązań, które widziałem w niektórych bibliotekach, jest umieszczenie tego udostępnionego kodu jako publicznego, ale udokumentuj, że jest on przeznaczony dla biblioteki wewnętrznej tylko do użytku.