web-dev-qa-db-fra.com

Pourquoi ma sous-classe ne peut-elle pas accéder à une variable protégée de sa superclasse, quand elle est dans un autre paquet?

J'ai une classe abstraite, relation dans le paquet database.relation et une sous-classe de celui-ci, Join, dans le paquet database.operations. relation a un membre protégé nommé mStructure.

Dans 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);
        }
    }
}

Sur des lignes

this.copyStructure(mRelLeft.mStructure);

et

for (final Header header : mRelRight.mStructure) {

Je reçois l'erreur suivante:

La relation de champ.mstructure n'est pas visible

Si je mettez les deux classes dans le même paquet, cela fonctionne parfaitement. Quelqu'un peut-il expliquer ce problème?

31
Amir Rachum

Cela fonctionne, mais seuls vous les enfants essaient d'y accéder propre variable, pas variable d'une autre instance (même s'il appartient au même arborescence d'héritage).

Voir cet exemple de code pour mieux comprendre:

//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 nous essayons de compiler en utilisant le withParent.parentVariable nous avons:

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

Il est accessible, mais seulement à sa propre variable.

25
OscarRyz

Un peu de mise en garde connue sur protégée :

6.6.2 Détails sur l'accès protégé

Un membre protégé ou un constructeur d'un objet peut être accessible de l'extérieur de l'emballage dans lequel il n'est déclaré que par code responsable de la mise en œuvre de cet objet.

13
Marcus Adams

Si protected, votre instance de Join ne peut pas accéder à mStructure dans d'autres instances (relRight, relLeft) en dehors du package.

ÉDITER:

La table ici explique cette situation assez bien. J'ai marqué le coupable dans votre question avec []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
2
Lauri Lehtinen

Le problème est que vous accédez à un autre membre protégé d'instance.

Vous pouvez appliquer plusieurs solutions, par exemple si possible, vous pouvez déclarer dans la classe mère ces deux méthodes:

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);
    }
  }
}

Puis dans le code des enfants remplacer:

this.copyStructure(mRelLeft.mStructure);

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

Avec:

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

Cela devrait fonctionner. Maintenant, la relation a la responsabilité de fournir des méthodes qui permettent des opérations avec elle-même à ses enfants. La raison de cette politique est probablement que les enfants ne devraient pas gâcher les internes des parents à moins qu'ils ne font partie du même paquet logiciel afin de limiter les incompatibilités.

0
user1039663