How to make an outer class inherited from an inner class?

How can I do something like this work:

class Outer { int some_member; abstract class InnerBase { abstract void method(); } } class OuterExtendsInner extends Outer.InnerBase { OuterExtendsInner(Outer o) { o.super(); } void method() { // How do I use some_member here? // Writing Outer.this.some_member -> error about Outer not being an enclosing class // Writing just some_member -> no-go, either } } 

The workaround is the InnerBase method, which returns Outer.this and calls THAT from derived classes, but is there any other way?

First of all, I want to extend InnerBase from the outside to have better code organization, but I could move all the derived classes to Outer.

+8
java inner-classes
source share
7 answers

The problem is that the synthetic field that binds InnerBase to Outer is a private field. Thus, we can only access an external object from InnerBase , or if any method or field contains a link to the same object.

+3
source share

You can do this in OuterExtendsInner :

 class OuterExtendsInner extends Outer.InnerBase { Outer o; OuterExtendsInner(Outer o) { o.super(); this.o = o; } void method() { // now you can reference o.some_member int x = o.some_member; } } 
+3
source share

Answer: you cannot, because it will break encapsulation. Only InnerBase can access Outer attributes, not OuterExtendsInner. This is not direct inheritance. InnerBase does not inherit Outer.

+1
source share

I have not tried to answer WhiteFang34. This might work, but I don't understand how to do it ...

If you really want to define an extension of your inner class elsewhere than in the outer class, it would be most natural to define it as an extension of the inner class in another outer extension of your outer class as follows:

 class Outer { int some_member; abstract class InnerBase { abstract void method(); } } class OuterExtendsOuter extends Outer { class InnerExtendsInner extends Outer.InnerBase { void method() { System.out.println(some_member); } } } 

I don't run this code either, but it should work.

Update:

Based on the comment stream, I now compiled and executed both my code above and the WhiteFang34 code.

Both really work, but as noted in the comments of Pailo Eberman, both create two copies of the outer inside the built-in inner class.

I am going to support Pailo, and I will defend, just not trying to do it with tactics, as this is really an abuse of the inner class mechanism.

Just make your extended inner classes live inside the same outer class!

Update 2:

What happens in my code, based on checking the runtime using the debugger and when checking the output from the javap class checks, is that both InnerBase and OuterExtendsOuter$InnerExtendsInner have synthetic private final fields called this$0 . Since constructors are not explicitly defined, default constructors are used, and the code snippet

  OuterExtendsOuter outer = new OuterExtendsOuter(); Outer.InnerBase inner = outer.new InnerExtendsInner(); 

forces these two fields to refer to outer .

In other words, Paŭlo's comment is completely correct.

InnerBase further experimentation, the same thing happens if you extend InnerBase in another inner class outer , so it has little to do with being defined in the same outer class or its extension, but it is in fact how non-static inner classes are usually processed.

I suspect this is documented somewhere, but I have not seen it.

Perhaps it's best to mix inheritance and inner classes as little as possible!

+1
source share

Just enter getter method in InnerBase?

 class Outer { int some_member; abstract class InnerBase { abstract void method(); protected int getSome_Member() // This is possible, because Abstract classes can have non-abstract methods. { return some_member; } } } class OuterExtendsInner extends Outer.InnerBase { OuterExtendsInner(Outer o) { o.super(); } void method() { // you can access "some_member" now int myNumber = getSome_Member(); } } 
+1
source share

Well, your problem is that every InnerBase instance (I know it's abstract) should have a reference to an Outer object. This is part of the semantics of nested classes. Creating an instance of OuterExtendsInner will require such a reference. You can avoid creating InnerBase a static nested class.

0
source share

The outer class can extend the inner class if the inner class is compiled into ".class".

Now, every time you compile the outer class, it encounters "extends innerclass", which

not compiled yet, and the compiler will throw a NoClassDefException or ClassNotFoundException.

Is that not so? This way you will never get this inner class. If you can solve this problem

then you can also extend the inner class :).

0
source share

All Articles