当涉及内部类时,Java继承如何工作

mar*_*ega 11 java polymorphism inheritance inner-classes

当内部类存在时,我无法理解继承在Java中的工作原理.我正在研究一个子类需要稍微改变它的父类内部类的功能的东西.我在下面提出了一个更简单,更简单的例子.

我希望这段代码打印"我是一个ChildClass.InnerClass",而是打印"我是一个ParentClass.InnerClass".为什么是这样?此外,如果我将main中的obj对象更改为ChildClass类型,则输出将更改为"我是ChildClass.InnerClass".为什么是这样?

一般来说,改变对象父类内部对象行为的推荐方法是什么?

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();
   }
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*378 8

变量不像方法那样"覆盖".

在你的电话,你所期望x成为Child的一个,但它是不是因为x是一个变量,而不是一个方法.

但要注意:你的引用类型是ParentClass这样obj.x指向ParentClassInnerClass属性,即使真正的实例背后parentClass是一个ChildClass!

为了显示您期望的句子,您必须将类型引用更改为ChildClass:

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

为了更好地理解这个概念,尝试在两个类ParentClassChildClass类中定义一个方法:

public InnerClass getInnerClass(){
  return x;
}  
Run Code Online (Sandbox Code Playgroud)

并使x私人.

所以"覆盖概念"适用.

在这种情况下,您的最终通话将是:

ParentClass obj = (new InnerClassTest()).new ChildClass();
obj.getInnerClass().speak();
Run Code Online (Sandbox Code Playgroud)

要改变内部类的行为,请考虑模板方法模式或更好:策略模式(因为更尊重DIP)