database.relation
パッケージにrelation
という抽象クラスと、database.operations
パッケージにそのサブクラスJoin
があります。 relation
には、mStructure
という名前の保護されたメンバーがあります。
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);
}
}
}
オンラインで
this.copyStructure(mRelLeft.mStructure);
そして
for (final Header header : mRelRight.mStructure) {
次のエラーが発生します。
フィールドRelation.mStructureは表示されません
両方のクラスを同じパッケージに入れると、これは完全に機能します。誰でもこの問題を説明できますか?
動作しますが、子だけがアクセスしようとしますown変数であり、他のインスタンスの変数ではありません(同じ継承ツリーに属している場合でも)。
理解を深めるには、次のサンプルコードをご覧ください。
//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
}
}
withParent.parentVariable
を使用してコンパイルしようとすると、次のようになります。
Children.Java:8: parentVariable has protected access in parentpackage.Parent
System.out.print(withParent.parentVariable);
アクセス可能ですが、独自の変数にのみアクセスできます。
保護されている についてのほとんど知られていない警告:
6.6.2保護されたアクセスの詳細
オブジェクトの保護されたメンバーまたはコンストラクターは、そのオブジェクトの実装を担当するコードによってのみ宣言されているパッケージの外部からアクセスできます。
protected
の場合、Join
のインスタンスは、パッケージ外の他のインスタンス(mStructure
、relRight
)のrelLeft
にアクセスできません。
編集:
表 here は、この状況をかなりよく説明しています。質問の犯人に[]
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つのメソッドを宣言できます。
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);
}
}
}
そして、子コードで以下を置き換えます:
this.copyStructure(mRelLeft.mStructure);
for (final Header header :mRelRight.mStructure) {
if (!mStructure.contains(header)) {
mStructure.add(header);
}
}
と:
this.copyRelationStructure(mRelLeft);
this.mergeRelationStructure(mRelRight);
うまくいくはずです。現在、Relationは、自身の内部での操作を子に許可するメソッドを提供する責任があります。おそらく、このポリシーの背後にある理由は、非互換性を制限するために、同じソフトウェアバンドルの一部でない限り、子供が親の内部を混乱させてはならないことです。