14

当存在内部类时,我无法理解继承在 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();
   }
}
4

3 回答 3

9

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

在您的通话中,您希望x成为Child's 的人,但这不是因为它x是一个变量,而不是一种方法。

但请注意:您的引用类型ParentClass如此obj.x指向ParentClass'InnerClass属性,即使后面的真实实例parentClassChildClass!

为了显示您的预期句子,您必须将类型引用更改为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)

于 2012-10-23T23:07:22.830 回答
3

删除重新声明

InnerClass x; 

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

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

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

ChildClass obj; 
//obj.x means the x in child
于 2012-10-23T23:11:43.807 回答
0

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

我建议一开始就使用不那么复杂的设计。子类应该通过重写其方法来修改其父类的行为,因此我只需添加一些工厂方法newInnerClass()来重写此依赖项的创建,并在类层次结构的顶部管理此对象。

这将比您建议的更灵活,因为newInnerClass()只要它具有正确的接口,就可以实例化在任何地方定义的类。

于 2012-10-23T23:31:34.920 回答