私は実際に自分自身で解決できる問題がありましたが、私の元のコードがうまくいかない理由や理解できません。見つかりました。私はここに私のコードの簡略版を提示しています。ジェネリックで「プライベートアクセスがあります」エラー
は、次の抽象スーパーXを考えてみましょう:M1が呼び出されると
public abstract class X{
private int i;
public void m1(X x){
x.i = 1;
m2(x);
}
public abstract void m2(X x);
}
は、我々は、渡されたインスタンスのXのプライベートフィールドを操作して、私たちはそのインスタンスに平方メートルを呼び出します。
私はXのいくつかのサブクラスを持っています。彼らは、それらが操作するプライベートメンバーも宣言しているという意味で同じです。それを達成するために、彼らは常にm2の冒頭にキャストを行う必要があります。
public class Y extends X{
private int j;
public void m2(X x){
Y y = (Y) x;
y.j = 0;
}
}
しかし - 私はXのサブクラスのインスタンスのM1のすべての呼び出しは常に、例えば、同じタイプのものであり、パラメータを持っていることを保証することができます:ここではそのうちの一つであります私がYのインスタンスを持つとき、メソッドm1のパラメータは常にYの別のインスタンスになります。
その保証のため、ジェネリックを導入することでキャストを不要にしたいと考えました。これは私のサブクラスが次のようになるようにするためです:
public class Y extends X<Y>{
private int j;
public void m2(Y y){
y.j = 0;
}
}
スーパークラスXはどのようにして表示されますか?私の最初の試みであることが確認された:
public abstract class X<T extends X<T>>{
private int i;
public void m1(T x){
x.i = 1;
m2(x);
}
public abstract void m2(T x);
}
しかし - 動作しない、私はこれをコンパイルするとき、私は次のエラーを取得:あなたはプライベートにアクセスしようと何を得る通常だ
X.java:6: error: i has private access in X
を別のクラスのメンバー。明らかに、Javaは、Tが常にXのインスタンスであることを認識しませんが、宣言で「T extends X」を使用しました。
私はこのようなXを固定:
public abstract class X<T extends X<T>>{
private int i;
public void m1(T x){
X<?> y = x;
y.i = 1;
m2(x);
}
public abstract void m2(T x);
}
少なくとも私は、任意のより多くのキャストを使用していない - しかし、なぜ必要なこの余分な割り当てがありますか?そして、元のコードはなぜ機能しませんでしたか?また、私はX<?>
を使用しなければならず、X<T>
を使用できなかったことが奇妙なことを発見しました。
2番目のコードサンプルはコンパイルされませんでしたが、コンパイラは元のコードを批評するのに完全に正しいと思いました。この詳細な説明をありがとうございます! – Bernhard
確かにここでのメッセージは、 'private'がサブクラスからアクセスしたい任意のフィールドに使う誤ったアクセス修飾子であるということでしょうか?代わりにprotected修飾子を使用したり、ゲッターメソッドを提供したりするのはなぜですか? – Bobulous
Arkanon - 私はサブクラスのフィールドにアクセスしていないので、それを非公開にしたいのです。コードをもう一度見ると、宣言しているクラスのプライベートフィールドにアクセスしていることがわかります。さもなければ、それはキャストであってもコンパイルエラーになります! – Bernhard