2010-06-18 11 views
29

Tengo una clase abstracta, relation en el paquete database.relation y una subclase de ella, Join, en el paquete database.operations. relation tiene un miembro protegido llamado mStructure.¿Por qué mi subclase no puede acceder a una variable protegida de su superclase, cuando está en un paquete diferente?

En Join:

public Join(final Relation relLeft, final Relation relRight) { 
     super(); 
     mRelLeft = relLeft; 
     mRelRight = relRight; 
     mStructure = new LinkedList<Header>(); 
     this.copyStructure(mRelLeft.mStructure); 

     for (final Header header :mRelRight.mStructure) { 
     if (!mStructure.contains(header)) { 
      mStructure.add(header); 
     } 
    } 
} 

En las líneas

this.copyStructure(mRelLeft.mStructure); 

y

for (final Header header : mRelRight.mStructure) { 

me sale el siguiente error:

The field Relation.mStructure is not visible

Si pongo ambas clases en el mismo paquete, esto funciona perfectamente. ¿Alguien puede explicar este problema?

Respuesta

25

funciona, pero sólo usted los niños intenta acceder a él propia variables, no variables de otra instancia (incluso si pertenece al mismo árbol de herencia).

Ver este código de ejemplo para entenderlo mejor:

//in Parent.java 
package parentpackage; 
public class Parent { 
    protected String parentVariable = "whatever";// define protected variable 
} 

// in Children.java 
package childenpackage; 
import parentpackage.Parent; 

class Children extends Parent { 
    Children(Parent withParent){ 
     System.out.println(this.parentVariable);// works well. 
     //System.out.print(withParent.parentVariable);// doesn't work 
    } 
} 

si tratamos de compilar utilizando el withParent.parentVariable tenemos:

Children.java:8: parentVariable has protected access in parentpackage.Parent 
    System.out.print(withParent.parentVariable); 

Es accesible, pero sólo a su propia variable .

+0

¿Será una solución adecuada definir un descriptor de acceso protegido? –

+1

Lo mismo sucedería. Más interesante sería saber si 'Join' IS-A' Relation' y si es así, ¿por qué deberían ir en diferentes paquetes? Probablemente, usar un objeto intermedio para abstraer la estructura y lo haría. Le sugiero que los mueva en el mismo paquete por el momento, solo para evitar entrar en una parálisis de codificación. – OscarRyz

+0

Creo que su primera frase sería un poco más precisa si dice que dentro de la clase hija puede acceder a ese miembro en cualquier instancia de la clase secundaria, * o cualquier instancia de una clase que hereda de la clase secundaria *, pero no cualquier instancia de una clase de la cual la clase hija hereda. (Consulte la sección 6.6.2.1 de la especificación: http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.2). Por lo tanto, puede verlo en miembros derivados del árbol de herencia, pero no en miembros menos derivados. –

2

Si protected, la instancia de Join no puede acceder al mStructure en otros casos (relRight, relLeft) fuera del paquete.

EDIT:

La tabla here explica esta situación bastante bien. Marqué el culpable de su pregunta con [] s

Access Levels 
Modifier Class Package Subclass World 
public  Y  Y  Y   Y 
protected Y [Y]  Y   N 
no modifier Y  Y  N   N 
private  Y  N  N   N 
+0

Mmmhh su primera explicación solo dice, el OP pregunta, en primer lugar, * "no puede acceder a ella" *. Tu edición no aclara el problema. – OscarRyz

+0

Creo que mi primera explicación dice más o menos lo mismo que la tuya. –

+0

Y con respecto a la edición, ¿cómo no aclara la tabla el problema? El OP describió el mismo comportamiento que cabría esperar basado en la tabla: una instancia de una clase puede acceder a los miembros protegidos de otra instancia de cualquier clase, si residen en el mismo paquete. Además, una instancia de una clase puede acceder a los miembros protegidos definidos en su clase principal, incluso si la clase principal está en otro paquete. –

13

Una pequeña salvedad conocida sobre protected:

6.6.2 Details on protected Access

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

+2

Encuentro el ejemplo en §6.6.7 útil aquí. – Artefacto

+0

Y la definición formal que aclara "responsable de la implementación" se encuentra en §6.6.2.1 – meriton

0

El problema es que está accediendo a otro miembro protegido de instancia.

Puede aplicar múltiples soluciones, por ejemplo, si es posible se puede declarar en la clase padre de estos dos métodos:

protected void copyRelationStructure(Relation r) { 
    this.copyStructure(r.mStructure); 
} 

protected void mergeRelationStructure(Relation r) { 
    for (final Header header: r.mStructure) { 
    if (!mStructure.contains(header)) { 
     mStructure.add(header); 
    } 
    } 
} 

Y luego en Childs código Reemplazar:

this.copyStructure(mRelLeft.mStructure); 

for (final Header header :mRelRight.mStructure) { 
    if (!mStructure.contains(header)) { 
    mStructure.add(header); 
    } 
} 

Con:

this.copyRelationStructure(mRelLeft); 
this.mergeRelationStructure(mRelRight); 

Eso debería funcionar.Ahora, la relación tiene la responsabilidad de proporcionar métodos que permitan operar consigo mismos a sus hijos. Probablemente la razón detrás de esta política es que los niños no deben meterse con las partes internas de los padres a menos que sean parte del mismo paquete de software con el fin de limitar las incompatibilidades.

Cuestiones relacionadas