【问题标题】:How does Java inheritance work when inner classes are involved涉及内部类时 Java 继承如何工作
【发布时间】:2012-10-13 23:42:03
【问题描述】:

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

【问题讨论】:

  • 如果第二个InnerClass 扩展ParentClass.InnerClass 那么它的构造函数将调用ParentClass 构造函数。因此用ParentClass 的Innerclass 隐藏ChildClass 的Innerclass

标签: java inheritance polymorphism inner-classes


【解决方案1】:

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

在您的通话中,您希望 xChild 的那个,但这不是因为 x 是一个变量,而不是一个方法。

但请注意:您的引用类型是ParentClass,所以obj.x 指向ParentClassInnerClass 属性,即使parentClass 后面的真实实例是ChildClass

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

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

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

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

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

    【讨论】:

    • ParentClass obj; //obj.x means the x in child ??你的意思是 ChildClass obj;
    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多