У меня была проблема, я мог бы решить сам, но я до сих пор не понимаю, почему мой исходный код не работает, или если есть более элегантное решение, чем тот, который я найденный. Я представляю упрощенную версию моего кода здесь.Ошибка «с частным доступом» с генераторами
Рассмотрим следующий абстрактный суперкласс X:
public abstract class X{
private int i;
public void m1(X x){
x.i = 1;
m2(x);
}
public abstract void m2(X x);
}
Когда m1 называется, мы манипулируем личное поле X экземпляра прошло, а затем мы называем м2 с этим экземпляром.
У меня есть несколько подклассов X, они все одинаковы в том смысле, что они также объявляют частные члены, которыми они манипулируют. Чтобы достичь этого, им всегда нужно сделать бросок в начале м2. Вот один из них:
public class Y extends X{
private int j;
public void m2(X x){
Y y = (Y) x;
y.j = 0;
}
}
Но - я могу гарантировать, что каждый вызов m1 экземпляра подкласса X всегда будет иметь параметр, который имеет тот же тип, например, когда у меня есть экземпляр 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>
.
И меня неожиданно показало, что ваш второй образец кода не будет компилироваться, но, зная это, компилятор был совершенно прав, чтобы критиковать мой оригинальный код. Большое спасибо за подробное объяснение! – Bernhard
Несомненно, сообщение должно состоять в том, что 'private' является неправильным модификатором доступа для использования в любом поле, которое вы хотите использовать для подклассов? Почему бы вам не использовать защищенный модификатор или предоставить метод getter? – Bobulous
Arkanon - Я не получаю доступ к полю в подклассах, поэтому я хочу сохранить его в тайне. Если вы снова посмотрите на код, вы увидите, что я обращаюсь к частному полю внутри класса, я его объявляю. В противном случае это была бы ошибка компиляции, даже при использовании! – Bernhard