Доступ к защищенному внутреннему классу предка из класса-наследника
В трех разных пакетах размещены:
- интерфейс (MyInterfaceInner);
- класс предок (GeneralClass), имеющий защищенный внутренний класс (ProtectedClass);
- класс наследник (DerivativeClass).
Не могу в классе наследника написать метод, возвращающий ссылку на объект внутреннего класса предка. Идея предлагает сделать класс ProtectedClass public, в этом случае все работает.
Т.к. модификатор protected распространяет свой доступ и на наследников (а это вроде мой случай), то удивляет то, что код не компилируется. Кто-нибудь может пояснить в чем дело?
public interface MyInterfaceInner {
void print();
}
public class GeneralClass {
protected class ProtectedClass implements MyInterfaceInner {
@Override
public void print() {
System.out.println("Как здорово, что все мы здесь сегодня собрались");
}
}
}
public class DerivativeClass extends GeneralClass {
public ProtectedClass getProtectedClass() {
GeneralClass g = new GeneralClass();
// в этой строке код не компилируется
GeneralClass.ProtectedClass p = g.new ProtectedClass();
return p;
}
}
Ответы (1 шт):
Прежде всего следует отметить, что указанная проблема не воспроизводится для кода, представленного в вопросе, так как в нём все классы находятся в одном и том же пакете по умолчанию.
Поэтому код, приведённый в вопросе, должен был непосредственно указывать, что все классы находятся в отдельных пакетах.
Фактически проблема, описанная в вопросе, связана с тем, что неявные конструкторы по умолчанию имеют тот же спецификатор доступа, что и класс, в котором они описаны, то есть, у класса ProtectedClass его неявный конструктор по умолчанию также является protected.
То есть, доступ к такому конструктору возможен только из класса, который:
- принадлежит к тому же пакету, что и класс
GeneralClass.ProtectedClass - является подклассом класса
GeneralClass.ProtectedClassчто не выполняется для классаDerivativeClass, который наследует только внешний классGeneralClass.
Поэтому следует либо обеспечить доступ как минимум к конструктору класса GeneralClass.ProtectedClass, сделав его открытым:
public class GeneralClass {
protected class ProtectedClass implements MyInterfaceInner {
public ProtectedClass() {} // нужен открытый доступ
@Override
public void print() {
System.out.println("ProtectedClass");
}
}
}
Разумеется, если бы у класса ProtectedClass (и соответственно его конструктора по умолчанию) был открытый доступ, указанной проблемы не возникло бы.
Либо следует в классе DerivativeClass дополнительно создать внутренний класс -- потомок класса ProtectedClass и возвращать соответственно его экземпляр:
public class DerivativeClass extends GeneralClass {
protected class DerivedProtectedClass extends ProtectedClass {
@Override
public void print() {
System.out.println("derived protected");
}
}
public ProtectedClass getProtectedClass() {
// всё работает!
GeneralClass.ProtectedClass p = new DerivativeClass().new DerivedProtectedClass();
return p;
}
}
Аналогичный вопрос на основном SO: Protected nested class not accessible to derived classes in other package (2012)