简体   繁体   中英

How does polymorphism work for inner classes?

When I tried to understand how to work with collections in java, I realised that I don't understand how polymorphism works for inner classes.

Simple code example:

 class Parent {
    public static void main(String[] args) {
        new Parent().newInnerClass().myMethod();
        new Child().newInnerClass().myMethod();
    }

    public I newInnerClass() {
        return new InnerClass();
    }

    private final class InnerClass implements I {

        @Override
        public void myMethod() {
            System.out.println("parent inner class");
            foo();
        }
    }

    public void foo() {
        System.out.println("foo from parent");
    }


}

class Child extends Parent {
    public void foo() {
        System.out.println("foo from child");
    }
}

interface I {
    void myMethod();
}

result:

parent inner class
foo from parent
parent inner class
foo from child

Therefore first link affects the third method invocation. It is surprising to me.

Initially I thought that needed methods selected accordind to the link. But new Parent().newInnerClass() and new Child().newInnerClass() are links to InnerClass from Parent .

Can you clarify my misunderstanding?

PS

If InnerClass was in Child and extended InnerClass from Parent - this behaviour wouldn't be surprising for me.

There are no special rules for polymorphism in inner classes.

Inner class differs from regular class in two things:

  • Inner class holds an implicit reference to its containing object
  • Inner class can access private methods of its containing class (not relevant here)

That's how you can rewrite your example without inner class:

class Parent {
    ...
    public I newInnerClass() {
        return new NotInnerClass(this);
    }
    ...
}
class NotInnerClass implements I {
    private final Parent containingObject;

    public NotInnerClass(Parent containingObject) {
        this.containingObject = containingObject;
    }

    @Override
    public void myMethod() {
        System.out.println("parent inner class");
        containingObject.foo();
    }
}

This code produces the same output as your, because when you invoke

new Child().newInnerClass().myMethod();

containingObject is a Child and containingObject.foo() is a regular polymorphic call.

When you use inner class, compiler does the same thing behind the scenes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM