2010-12-17 43 views
5

Una cosa que siempre me ha molestado en Java es:clases públicas Java con clases privadas dependientes

¿Cómo se crea una sola clase pública que debe ser utilizado por los consumidores aguas abajo pero luego organizar bien las clases de los que depende en paquetes?

Por ejemplo (algo inventado), tengo una clase UserDao que se basa en LdapPersistenceHelper y DBPersistenceHelper. La clase UserDao está en un paquete llamado com.company.dao y me gustaría que los dos asistentes vivan en un paquete llamado com.company.dao.persistencehelper. Sin embargo, no quiero hacer que los dos ayudantes sean lo suficientemente genéricos como para que puedan ser utilizados por otros. ¿Cómo hago eso? Si hago que los ayudantes estén "protegidos" (realmente, no hay ningún modificador), entonces no puedo acceder a ellos desde el UserDao. Si los hago públicos, alguien más podría usarlos.

Respuesta

1

Una opción es colocarlos en el mismo paquete que la clase pública, pero con acceso al paquete.

Si está utilizando OSGi, puede dejar los paquetes de implementación fuera del conjunto de paquetes exportados.

+0

interesante, no había pensado en usar OSGI para resolver este problema – silk

3

No hay forma de hacer cumplir esto, a menos que coloque las clases en el mismo paquete. No hay manera de definir la visibilidad del subpaquete.

+0

Tengo una pregunta. Si utilizo una biblioteca con una clase sin modificador, solo se puede usar en ese paquete. Y creo un paquete con el mismo nombre en mi proyecto. ¿Puedo usar la clase en la biblioteca en mi propio paquete de esta manera? –

+0

Sí. Pero el lenguaje está diseñado para prevenir accidentes, no malversación. Stroustrup nota la misma distinción para C++ en D y E. –

+0

sí, puedes. Excepto si es java.lang, lava.util, etc.:) – Bozho

6

El problema de raíz es que estás tratando de usar paquetes para "organizar las cosas bien". Cuando se crearon los paquetes de Java, había dos objetivos de diseño: (1) denominación de clase globalmente única y (2) facilitar el uso del modificador de acceso protegido/predeterminado.

El hecho de que esté obligado a tener una estructura de carpeta de origen que coincida con los paquetes conduce inevitablemente a tratar de usarlos para crear una "estructura de carpeta bonita/organizada". Pero eso no es para lo que fue creado, y como consecuencia, no funciona muy bien con los modificadores de acceso para los que fue creado.

Editar: Como un lado, no estoy pasando el juicio de una manera u otra. Me di cuenta de que mi primera oración puede sonar crítica. Muchos proyectos eligen legítimamente una estructura organizada y sostenible en lugar de tratar de exprimir un poco más de valor percibido del acceso protegido. ¿Es realmente tan malo si la utilidad auxiliar es pública? Si no confía en los otros desarrolladores con acceso para no hacer un mal uso, ¿se puede confiar en que no solo modifiquen los modificadores de acceso?

+0

mientras que Bozho responde estrictamente a esta pregunta, me gusta más esta respuesta porque aprecia el problema de diseño – silk

+0

+1, esta es, de lejos, la respuesta superior. Si no está preparado para hacer que las clases de ayuda se adhieran a una interfaz pública o sean una utilidad genérica utilizable, es probable que no tengan cabida en su propio paquete. De hecho, si no tienen sentido fuera del contexto de una instancia de UserDao, probablemente no pertenezcan a su propio archivo de clase. –

+0

@Tim: Eso es evidentemente falso. Es posible que tenga una biblioteca completa de código reutilizable que generalmente no desea distribuir para uso externo y, por lo tanto, se contrae implícitamente para proporcionar compatibilidad binaria futura con ellos. –

1

No me preocuparía que otros las usen. Solo documéntelos como paquetes internos, tal vez incluso póngalos en un paquete "interno" o "impl". Si alguien los usa de manera inapropiada, solo pueden lastimarse y culparse a sí mismos (el único daño podría ser lidiar con cambios incompatibles con esas clases).

Si desea un aislamiento más fuerte, use OSGi.

1

Nota: Una posible forma de evitar esto (si está distribuyendo un JAR para que otros lo usen) es usar un obfuscater (recomiendo ProGuard) para ocultar las clases consumibles no públicas; una vez más, esto no evita la mala práctica deliberada, pero deja bastante claro que no existe un contrato para la compatibilidad con esas clases (y que técnicamente es difícil encontrar la manera de usarlas).

Cuestiones relacionadas