2010-06-18 12 views
29

Ich habe eine abstrakte Klasse, relation in Paket database.relation und eine Unterklasse davon, Join, in Paket database.operations. relation hat ein geschütztes Mitglied mit dem Namen mStructure.Warum kann meine Unterklasse nicht auf eine geschützte Variable ihrer Oberklasse zugreifen, wenn sie sich in einem anderen Paket befindet?

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

Auf Linien

this.copyStructure(mRelLeft.mStructure); 

und

for (final Header header : mRelRight.mStructure) { 

ich die folgende Fehlermeldung erhalten:

The field Relation.mStructure is not visible

Wenn ich beide Klassen in ein Paket legen, funktioniert das perfekt. Kann jemand dieses Problem erklären?

Antwort

25

Es funktioniert, aber nur die Kinder versucht es eigenes Variable zuzugreifen, nicht variabel einer anderen Instanz (auch wenn sie zu demselben Vererbungsbaum gehört).

diesen Beispielcode anzeigen, besser zu verstehen:

//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 
    } 
} 

Wenn wir versuchen, die withParent.parentVariable mit kompilieren wir haben:

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

Es ist zugänglich, sondern nur auf seine eigene Variable .

+0

Wird eine geeignete Lösung sein, einen geschützten Accessor zu definieren? –

+1

Das gleiche würde passieren. Interessanter wäre es zu wissen, ob "Join" IS-A "Relation" ist und wenn ja, warum sollten sie in verschiedenen Paketen gehen. Wahrscheinlich, ein Zwischenobjekt zu verwenden, um die Struktur zu abstrahieren und zu tun. Ich würde vorschlagen, dass Sie sie im selben Paket für jetzt verschieben, nur um zu vermeiden, in eine Codierungslähmung einzutreten. – OscarRyz

+0

Ich glaube, Ihr erster Satz wäre ein wenig genauer, wenn Sie sagen, dass Sie innerhalb der Kindklasse auf dieses Mitglied in jeder Instanz der Kindklasse * oder auf jede Instanz einer Klasse zugreifen können, die von der Kindklasse * erbt, aber nicht jede Instanz einer Klasse, von der die Kindklasse erbt. (Siehe Abschnitt 6.6.2.1 der Spezifikation: http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.2). Es kann es also in weiter abgeleiteten Mitgliedern des Vererbungsbaums sehen, nur nicht in weniger abgeleiteten Mitgliedern. –

2

Wenn protected, die Instanz von Join kann nicht auf die mStructure in anderen Fällen (relRight, relLeft) außerhalb des Pakets.

EDIT:

Die Tabelle here erklärt diese Situation ziemlich gut. Ich war den Täter in Ihrer Frage mit [] 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 deine erste Erklärung sagt nur, das OP fragt, an erster Stelle, * "kann nicht darauf zugreifen" *. Deine Bearbeitung, klärt das Problem nicht ganz. – OscarRyz

+0

Ich denke, meine erste Erklärung sagt ziemlich genau dasselbe wie deine. –

+0

Und in Bezug auf die Bearbeitung, wie erklärt die Tabelle das Problem nicht? Das OP beschrieb genau das Verhalten, das man aufgrund der Tabelle erwarten würde - eine Instanz einer Klasse kann auf die geschützten Mitglieder einer anderen Instanz einer Klasse zugreifen, wenn sie sich in demselben Paket befinden. Darüber hinaus kann eine Instanz einer Klasse auf die geschützten Member zugreifen, die in ihrer übergeordneten Klasse definiert sind, selbst wenn sich die übergeordnete Klasse in einem anderen Paket befindet. –

13

ein wenig bekannten Vorbehalt über 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

Ich finde das Beispiel unter §6.6.7 hier nützlich. – Artefacto

+0

Und die formale Definition zur Klärung "verantwortlich für die Umsetzung" ist in §6.6.2.1 – meriton

0

Das Problem besteht darin, dass Sie auf andere Instanz geschützte Mitglied zugreifen.

Sie können mehrere Lösungen anwenden, wenn beispielsweise möglich, dass Sie in der übergeordneten Klasse dieser beiden Methoden erklären können:

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

Und dann in Childs Code ersetzen:

this.copyStructure(mRelLeft.mStructure); 

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

mit:

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

Das sollte funktionieren.Jetzt hat Relation die Verantwortung, Methoden zur Verfügung zu stellen, die Operationen mit sich selbst an seine Kinder ermöglichen. Wahrscheinlich liegt der Grund für diese Richtlinie darin, dass Kinder sich nicht mit den Interna der Eltern anlegen sollten, wenn sie nicht demselben Softwarepaket angehören, um Inkompatibilitäten zu begrenzen.