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


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

9999
2017-10-23 23:02


起源

如果第二个 InnerClass  扩展 ParentClass.InnerClass 然后它的构造函数会调用 ParentClass 构造函数.thus 用ParentClass的Innerclass隐藏ChildClass的Innerclass - amarnath harish


答案:


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

在你的电话中,你期待 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();
}

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

public InnerClass getInnerClass(){
  return x;
}  

和做 x 私人的。

所以“覆盖概念”适用。

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

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

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


8
2017-10-23 23:07





删除重新声明

InnerClass x; 

来自儿童班。所以,你只有一个 x 并将在子类的构造函数中重新分配。这意味着一个 x (参考child ctor中创建的对象)。

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

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

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

3
2017-10-23 23:11



ParentClass obj; //obj.x means the x in child ??你的意思是ChildClass obj; - exexzian
@sansix:没错。谢谢你的编辑。 - Bhesh Gurung
+1解决方案 - exexzian


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

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

这比你建议的更灵活,因为 newInnerClass() 只要具有正确的接口,就可以实例化定义的类。


1
2017-10-23 23:31