How does Java inheritance work when inner classes are involved

16,706

Solution 1

Variable are not "overriden" as methods are.

In your call, you expected x to be the Child's one but it isn't because x is a variable, not a method.

But pay attention: Your reference type is ParentClass so obj.x points to the ParentClass's InnerClass attribute even though the real instance behind parentClass is a ChildClass!

In order to display your expected sentence, you have to change the type reference to ChildClass:

public static void main(String[] args) {
      ChildClass obj = (new InnerClassTest()).new ChildClass();
      obj.x.speak();
}

To better understand the concept, try to define a method in both ParentClass and ChildClass classes:

public InnerClass getInnerClass(){
  return x;
}  

and make x private.

so that "override concept" applies.

Your final call would be in this case:

ParentClass obj = (new InnerClassTest()).new ChildClass();
obj.getInnerClass().speak();

To alter the behavior of the inner classes, think of Template method pattern or better: Strategy pattern (since more respectful of DIP)

Solution 2

Remove the redeclaration

InnerClass x; 

from the child class. So, that you will have only one x and will be reassigned in the constructor of the child class. Which means one x (refering to the object created in child ctor).

It's hiding the one in the parent class. Which is why you end up having two fields, refering to two different objects. And due to static (compile-time or early) binding in case of variables,

ParentClass obj; 
//obj.x means the x in parent

and

ChildClass obj; 
//obj.x means the x in child
Share:
16,706

Related videos on Youtube

martega
Author by

martega

Updated on August 22, 2022

Comments

  • martega
    martega over 1 year

    I am having trouble understanding how inheritance works in Java when inner classes are present. I'm currently working on something where a child class needs to slightly change the functionality of the inner class of it's parent. I've come up with an simpler, analagous example below.

    I expected this code to print "I am a ChildClass.InnerClass" but instead it prints "I am a ParentClass.InnerClass". Why is this? Also, if I change the obj object in main to be of type ChildClass then the output changes to "I am a ChildClass.InnerClass". Why is this?

    In general, what is the recommended way of altering the behavior of an object's parent class's inner object?

    class InnerClassTest {
       //-----------------------------------------------------------------------
       // PARENT CLASS
       class ParentClass {
          public ParentClass() {
             x = new InnerClass();
          }
    
          InnerClass x;
    
          class InnerClass {
             public void speak() {
                System.out.println("I am a ParentClass.InnerClass");
             }
          }
       }
    
       //-----------------------------------------------------------------------
       // CHILD CLASS
       class ChildClass extends ParentClass {
          public ChildClass() {
             x = new InnerClass();
          }
    
          InnerClass x;
    
          class InnerClass extends ParentClass.InnerClass {
             public void speak() {
                System.out.println("I am a ChildClass.InnerClass");
             }
          }
       }
    
       //-----------------------------------------------------------------------
       // MAIN
       public static void main(String[] args) {
          ParentClass obj = (new InnerClassTest()).new ChildClass();
          obj.x.speak();
       }
    }
    
  • exexzian
    exexzian over 11 years
    ParentClass obj; //obj.x means the x in child ?? did you meant ChildClass obj;