2010-11-21 31 views
10

Bastante nuevo en Java, pero me pregunto por qué el acceso al paquete se considera "más restrictivo" que el acceso a la subclase. Es decir, cada modificador de acceso que proporciona subclases con acceso a un miembro también proporciona acceso a todo el paquete, y existen modificadores que proporcionan acceso de paquete pero no acceso de subclase.Java: Acceso a la subclase sin acceso al paquete

¿No es esto totalmente al revés? Digamos que tengo una clase ControlledInstantiation en algún paquete. Si tengo otra clase AlsoControlledInstantiation extends ControlledInstantiation, no puedo llamar al constructor de ControlledInstantiation a menos que lo configure como protegido o público. Y si lo configuro como protegido, ahora cualquier otra clase en el paquete puede instanciarlo tan a menudo como quiera. Entonces, algo que está obligado a ser sustituible por su superclase (y, sintácticamente, es) obtiene el mismo o menor acceso a la superclase que algo que cumple una función distinta pero relacionada. Es como decirle a su hijo que no puede jugar con su billetera porque no le permite a sus vecinos hacerlo y luego dejar que sus vecinos duerman en su casa porque su hijo sí.

Así que supongo que estoy preguntando, ¿qué motivó esta decisión y cómo puedo evitarla?

+0

pero está escribiendo el código para "ControlledInstantiation" y, por lo tanto, presumiblemente es el propietario del código en su paquete. ¿Está diciendo que no confía en usted mismo? – pstanton

+0

Cualquiera puede crear una nueva clase en cualquier paquete, excepto los que protege el cargador de clases. A menos que oculte el nombre del paquete de una clase usada internamente en todas mis interfaces documentadas (lo cual, pienso, es imposible, ya que incluso una fábrica tiene que importar la clase que crea, y en algún momento debe hacerse referencia a la fábrica, etc. .), cualquiera puede poner una clase en ese paquete. Es casi seguro que las personas no lo harían, a menos que quisieran hacer algo que no deberían hacer, pero podrían hacerlo. – Innominate

Respuesta

3

Al principio puede parecer al revés, pero la idea es que un paquete de Java debe contener un conjunto de clases comparativamente cohesivas que están semánticamente relacionadas, y esto se refleja en el modificador de paquete predeterminado. Entonces, la lógica es que si desea dar un paso más y permitir que las subclases de cualquier paquete visualicen sus miembros, puede declararlas como protegidas. ¿Tiene sentido para usted que las subclases de paquetes extranjeros sean menos confiables que cualquier clase (ya sea una subclase o no) de su propio paquete?

Java de hecho tenía una vez privado protegido modificador que conseguiría lo que busca, pero fue eliminado, me imagino, porque confundía a la gente. No estoy seguro de cómo podría lograr esto sin relegar cada par de clase/subclase a su propio paquete. Pero esa es una solución desordenada que va en contra de los principios de Java y de todos modos no funcionaría para las jerarquías de herencia de más de dos clases.

3

Tiene razón, este hecho es un poco confuso. Aquí están las soluciones alternativas que puedo sugerir.

  1. Su ejemplo con constructor protegido es más relevante para los métodos. En algunos casos, puede evitar el acceso al protegido constructor por miembro del paquete que no son las subclases de la clase actual si marca clase como abstract.

  2. Si realmente desea evitar el acceso al método protegido por miembros de paquetes se puede resolver este problema al menos en tiempo de ejecución utilizando Throwable.getStackTrace():

    if(!getClass().isAssignableFrom(
        Class.forName(new Throwable().getStackTrace()[1].getClassName()))) { 
         throw new IllegalAccessException(
          "This method can be accessed by subclass only"); 
    } 
    
+0

sus respuestas son buenas, pero aprenda a formatear ejemplos de código correctamente: http://stackoverflow.com/editing-help –

+0

Disculpe por el mal formato. Normalmente lo hago, pero esta vez traté de formatearlo varias veces y ¡simplemente no funcionó! – AlexR

0

Puede sellar un paquete. Ver la especificación del archivo JAR.