Tengo dos paquetes en mi proyecto: odp.proj
e odp.proj.test
. Hay ciertos métodos que quiero que sean visibles solo para las clases en estos dos paquetes. ¿Cómo puedo hacer esto?
EDITAR: Si no hay un concepto de subpaquete en Java, ¿hay alguna forma de evitarlo? Tengo ciertos métodos que quiero que estén disponibles solo para los evaluadores y otros miembros de ese paquete. ¿Debo simplemente tirar todo en el mismo paquete? ¿Usar una extensa reflexión?
java
package
visibility
encapsulation
Nick Heiner
fuente
fuente
Respuestas:
No puedes En Java no existe el concepto de un sub-paquete, por lo que
odp.proj
yodp.proj.test
son paquetes completamente separadas.fuente
Los nombres de sus paquetes sugieren que la aplicación aquí es para pruebas unitarias. El patrón típico utilizado es colocar las clases que desea probar y el código de prueba de la unidad en el mismo paquete (en su caso
odp.proj
) pero en diferentes árboles de origen. Así que pondrías tus clasessrc/odp/proj
y tu código de pruebatest/odp/proj
.Java tiene el modificador de acceso "paquete", que es el modificador de acceso predeterminado cuando no se especifica ninguno (es decir, no se especifica público, privado o protegido). Con el modificador de acceso "paquete", solo las clases
odp.proj
tendrán acceso a los métodos. Pero tenga en cuenta que en Java, no se puede confiar en los modificadores de acceso para hacer cumplir las reglas de acceso porque con la reflexión, cualquier acceso es posible. Los modificadores de acceso son meramente sugerentes (a menos que esté presente un administrador de seguridad restrictivo).fuente
Esta no es una relación especial entre
odp.proj
yodp.proj.test
, simplemente se les nombra como aparentemente relacionados.Si el paquete odp.proj.test simplemente proporciona pruebas, puede usar el mismo nombre de paquete (
odp.proj
). IDEs como Eclipse y Netbeans crearán carpetas separadas (src/main/java/odp/proj
ysrc/test/java/odp/proj
) con el mismo nombre de paquete pero con semántica JUnit.Tenga en cuenta que estos IDE generarán pruebas para los métodos
odp.proj
y crearán la carpeta adecuada para los métodos de prueba en los que no existe.fuente
Cuando hago esto en IntelliJ, mi árbol fuente se ve así:
fuente
Probablemente depende un poco de tus motivos para no mostrarlos, pero si la única razón es que no quieres contaminar la interfaz pública con las cosas destinadas solo para pruebas (o alguna otra cosa interna), pondría los métodos en un separe la interfaz pública y haga que los consumidores de los métodos "ocultos" usen esa interfaz. No impedirá que otros usen la interfaz, pero no veo ninguna razón por la que deba hacerlo.
Para pruebas unitarias, y si es posible sin reescribir el lote, siga las sugerencias para usar el mismo paquete.
fuente
Como han explicado otros, no existe un "subpaquete" en Java: todos los paquetes están aislados y no heredan nada de sus padres.
Una manera fácil de acceder a los miembros de la clase protegida desde otro paquete es extender la clase y anular los miembros.
Por ejemplo, para acceder
ClassInA
en paquetea.b
:crea una clase en ese paquete que anule los métodos que necesitas en
ClassInA
:Eso le permite usar la clase superior en lugar de la clase en el otro paquete:
Tenga en cuenta que esto solo funciona para miembros protegidos, que son visibles para las clases extendidas (herencia), y no para miembros privados de paquetes que son visibles solo para las clases sub / extendidas dentro del mismo paquete. ¡Ojalá esto ayude a alguien!
fuente
La mayoría de las respuestas aquí han declarado que no hay tal cosa como un subpaquete en Java, pero eso no es estrictamente exacto. Este término ha estado en la especificación del lenguaje Java desde Java 6, y probablemente más atrás (no parece haber una versión de JLS de libre acceso para versiones anteriores de Java). El lenguaje alrededor de los subpaquetes no ha cambiado mucho en el JLS desde Java 6.
Java 13 JLS :
El concepto de subpaquete es relevante, ya que impone restricciones de nomenclatura entre paquetes y clases / interfaces:
Sin embargo, esta restricción de nomenclatura es el único significado que el lenguaje otorga a los subpaquetes:
Con este contexto, podemos responder la pregunta en sí. Dado que no existe una relación de acceso especial entre un paquete y su subpaquete, o entre dos subpaquetes diferentes de un paquete padre, no hay forma dentro del lenguaje de hacer que un método sea visible para dos paquetes diferentes de la manera solicitada. Esta es una decisión de diseño intencional documentada.
O el método puede hacerse público y todos los paquetes (incluidos
odp.proj
yodp.proj.test
) podrán acceder a los métodos dados, o el método podría hacerse privado (la visibilidad predeterminada), y todo el código que necesita acceder directamente a él debe incluirse el mismo (sub) paquete que el método.Dicho esto, una práctica muy estándar en Java es colocar el código de prueba en el mismo paquete que el código fuente, pero en una ubicación diferente en el sistema de archivos. Por ejemplo, en la herramienta de compilación Maven , la convención sería colocar estos archivos fuente y de prueba en ,
src/main/java/odp/proj
ysrc/test/java/odp/proj
respectivamente. Cuando la herramienta de compilación compila esto, ambos conjuntos de archivos terminan en elodp.proj
paquete, pero solo lossrc
archivos se incluyen en el artefacto de producción; los archivos de prueba solo se usan en el momento de la compilación para verificar los archivos de producción. Con esta configuración, el código de prueba puede acceder libremente a cualquier código privado o protegido del paquete del código que está probando, ya que estarán en el mismo paquete.En el caso en que desee compartir código entre subpaquetes o paquetes hermanos que no sea el caso de prueba / producción, una solución que he visto que algunas bibliotecas usan es poner ese código compartido como público, pero documentar que está destinado a la biblioteca interna Usar unicamente.
fuente
Sin poner el modificador de acceso delante del método, dices que es un paquete privado.
mira el siguiente ejemplo.
fuente
Con la clase PackageVisibleHelper, y mantenerla privada antes de que PackageVisibleHelperFactory congelado, podemos invocar el método launchA (por PackageVisibleHelper) en cualquier lugar :)
fuente