Reputation: 39
I'm having trouble trying to implement this statement I read in Oracle's Docs about Inheritance when it comes to inner classes.
The statement :
A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.
In order to test this out i.e. to see if I can achieve the above I created a top level class OC1 which had an inner class IC1 ,then I created another top level class OC2 which extended IC1.
Before I could even start writing a single method , the IDE stopped me at the OC2 class body itself saying
"No enclosing instance of type DataStructure is available due to some intermediate constructor invocation"
I read some other answers and most of them point to either a) Changing the inner class to static Nested Class -- it resolves the error b) The whole scenario is unnecessary and convoluted.
Here is the code:
public class DataStructure {
// Create an array
private final static int SIZE = 15;
private int[] arrayOfInts = new int[SIZE];
public DataStructure() {
// fill the array with ascending integer values
super();
for (int i = 0; i < SIZE; i++) {
arrayOfInts[i] = i;
}
}
//other methods
//IC1
protected class instanceArr{
private int a = 8;
private static final int B = 4;
protected instanceArr(){
}
protected void doSomething(){
System.out.println("arrayOfInts[] is accessible " + arrayOfInts[6]);
}
}
//main method
}
OC2
public class DataStructureChild extends DataStructure.instanceArr{
public DataStructureChild(){
}
}
I know that the scenario is not an ideal one but I don't want to change inner class to static nested class - it would defeat my purpose of basically trying to see whether arrayOfInts is accessible without OC1's instance in hand.
Am I misinterpreting this statement ? if not then kindly point me in the correct direction.
PS - this is my first question here - apologies in advance if some guidelines were flouted.
Upvotes: 2
Views: 1481
Reputation: 40034
You can do this since you inherit access to the inner class of the parent.
class DataStructureChild extends DataStructure {
public DataStructureChild() {
}
public void foo() {
InstanceArr ins = new InstanceArr();
ins.doSomething();
System.out.println(ins.a);
}
}
But could you please give a link or explain where you read the following? A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.
The first part I knew about. But I never considered a separate class extending another classes inner class. Especially since there is usually an implicit relationship between classes and their enclosed inner classes.
Edit:
I believe you misunderstood the statement.
So it was just talking about access the inner class via inheritance, not extending it directly.
However, if you really want to do have that kind of inheritance relationship without passing references around, you can go this route.
public class Inheritance extends Outer.Inner {
public Inheritance() {
new Outer().super();
}
public static void main(String[] args) {
new Inheritance().start();
}
public void start() {
System.out.println(a);
method();
}
}
class Outer {
public Outer() {
}
protected class Inner {
protected int a = 10;
protected Inner() {
}
protected void method() {
System.out.println("This is a private message");
}
}
}
Upvotes: 0
Reputation: 1986
Yes, this is a Trap caused by Java's synthetic sugar. You think the inner-non-static-class have the default-no-arguments-constructor but that is wrong. Internally the constructor of IC1 have the OC1 as first argument in the constructor - even if you can not see it.
Thats why the OC2 constructor must use the OC1 as constructor-argument:
public DataStructureChild(DataStructure argument) {
}
Unfortunaltely this is not enougth, you need to get sure the argument is not-null:
public DataStructureChild(DataStructure argument) {
argument.super();
}
It looks very wierd but it works.
Upvotes: 3