Ответ 1
private
Доступ к элементам возможен только внутри класса, в котором они были объявлены. Поэтому, если у вас есть класс
class X{
private int field = 1;
private void method(){}
void foo(X x){
x.field = 2;
x.method(); // this is OK, because we are accessing members from instance of X
// via reference of class X (which is same class as this one)
}
void bar(Y y){// = lets assume that Y extends X
y.field = 3;
y.method(); // ERROR: we can't access `method()`
}
}
Как вы видите, нам не разрешен доступ к частному члену из производного класса, даже если мы внутри класса, в котором объявлен этот член.
Возможной причиной этого является то, что частные члены не наследуются для интерфейса производного класса (который является цельной целью модификатора видимости private
). Из-за этого в таких классах можно обновлять эти элементы любым способом, который хочет автор, например, кто-то может создать класс, подобный этому:
class Y extends X{
private String field = "foo";
private String method(){
return "bar";
}
}
Итак, как вы видите, возможно, что при вызове y.method()
вы пытаетесь получить доступ к method
, объявленному в классе Y
, но у вас нет доступа к нему из класса X
(из-за инкапсуляции), И это компилятор сценария предполагает , потому что поля и частные методы не являются полиморфными.
Чтобы избежать этой путаницы, вам нужно явно указать, что вы хотите вызывать частный член из текущего класса X, используя кастинг
void bar(Y y){
((X)y).method();
}
То же самое происходит для <T extends A>
. Поскольку T
может быть любым подклассом A
, компилятор не разрешит доступ к его частным членам. Поэтому вам нужно будет вернуть его обратно в A
class A<T extends A> {
private T one() { return (T) this;}
protected T two() { return (T) this;}
protected void three() { ((A)two()).one(); }
}