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

当存在内部类时,我无法理解继承在Java中是如何工作的。我目前正在研究一些东西,其中子类需要稍微改变其父类的内部类的功能。我在下面提出了一个更简单,更典型的例子。

我期望此代码打印“I am a ChildClass.InnerClass”,但它打印的是“I am a ParentClass.InnerClass”。这是为什么呢?此外,如果我将 main 中的 obj 对象更改为 ChildClass 类型,则输出将更改为“I am a 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();
   }
}

答案 1

变量不像方法那样被“覆盖”。

在你的调用中,你期望是的那个,但它不是,因为它是一个变量,而不是一个方法。xChildx

但请注意:您的引用类型是如此指向 的属性,即使后面的真实实例是 !ParentClassobj.xParentClassInnerClassparentClassChildClass

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

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

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

public InnerClass getInnerClass(){
  return x;
}  

并设为私有。x

因此,“覆盖概念”适用。

在这种情况下,您的最终调用将是:

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

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


答案 2

删除重新声明

InnerClass x; 

从子类。因此,您将只有一个,并将在子类的构造函数中重新分配。这意味着一个(引用在子 ctor 中创建的对象)。xx

它隐藏了父类中的那个。这就是为什么你最终会有两个字段,指的是两个不同的对象。并且由于在变量的情况下的静态(编译时或早期)绑定,

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

ChildClass obj; 
//obj.x means the x in child

推荐