简体   繁体   English

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

[英]How does Java inheritance work when inner classes are involved

I am having trouble understanding how inheritance works in Java when inner classes are present. 当存在内部类时,我很难理解继承在Java中的工作方式。 I'm currently working on something where a child class needs to slightly change the functionality of the inner class of it's parent. 我目前正在研究子类需要稍微更改其父类内部类功能的东西。 I've come up with an simpler, analagous example below. 我在下面提出了一个更简单,类似的示例。

I expected this code to print "I am a ChildClass.InnerClass" but instead it prints "I am a ParentClass.InnerClass". 我希望此代码可以打印“我是ChildClass.InnerClass”,但可以打印“我是ParentClass.InnerClass”。 Why is this? 为什么是这样? Also, if I change the obj object in main to be of type ChildClass then the output changes to "I am a ChildClass.InnerClass". 另外,如果我将main中的obj对象更改为ChildClass类型,则输出更改为“我是ChildClass.InnerClass”。 Why is this? 为什么是这样?

In general, what is the recommended way of altering the behavior of an object's parent class's inner object? 通常,建议的改变对象父类内部对象行为的方法是什么?

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();
   }
}

Variable are not "overriden" as methods are. 变量不像方法那样“被覆盖”。

In your call, you expected x to be the Child 's one but it isn't because x is a variable, not a method. 在您的通话中,您希望xChild但这不是因为x是变量,而不是方法。

But pay attention: Your reference type is ParentClass so obj.x points to the ParentClass 's InnerClass attribute even though the real instance behind parentClass is a ChildClass ! 但请注意:您的引用类型是ParentClass因此obj.x指向ParentClassInnerClass属性,即使parentClass背后的实际实例是ChildClass

In order to display your expected sentence, you have to change the type reference to ChildClass : 为了显示您期望的句子,您必须将类型引用更改为ChildClass

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

To better understand the concept, try to define a method in both ParentClass and ChildClass classes: 为了更好地理解该概念,请尝试在ParentClassChildClass类中都定义一个方法:

public InnerClass getInnerClass(){
  return x;
}  

and make x private. 并将x私有。

so that "override concept" applies. 因此,“替代概念”适用。

Your final call would be in this case: 在这种情况下,您的最终通话是:

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

To alter the behavior of the inner classes, think of Template method pattern or better: Strategy pattern (since more respectful of DIP) 要更改内部类的行为,请考虑使用模板方法模式或更好的方法策略模式 (因为更加尊重DIP)

Remove the redeclaration 删除重新声明

InnerClass x; 

from the child class. 来自儿童班。 So, that you will have only one x and will be reassigned in the constructor of the child class. 因此,您只有一个x并且将在子类的构造函数中重新分配。 Which means one x (refering to the object created in child ctor). 表示一个x (指的是在子ctor中创建的对象)。

It's hiding the one in the parent class. 它在父类中隐藏了一个。 Which is why you end up having two fields, refering to two different objects. 这就是为什么您最终拥有两个字段,分别引用两个不同的对象的原因。 And due to static (compile-time or early) binding in case of variables, 由于存在变量的静态(编译时或早期)绑定,

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

and

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

In general, what is the recommended way of altering the behavior of an object's parent class's inner object? 通常,建议的改变对象父类内部对象行为的方法是什么?

I'd recommend using a less convoluted design to begin with. 我建议一开始就使用较简单的设计。 A child class should modify the behaviour of its parent by overriding its methods, so I'd just add some factory method newInnerClass() to override the creation of this dependency, and manage this object at the top of the class hierarchy. 子类应该通过覆盖其方法来修改其父类的行为,因此我只需添加一些工厂方法newInnerClass()即可覆盖此依赖项的创建,并在类层次结构的顶部管理该对象。

This would be more flexible than what you propose, because newInnerClass() could instantiate a class that's defined wherever as long as it has the right interface. 这将比您建议的方法更加灵活,因为newInnerClass()可以实例化定义在任何地方的类,只要它具有正确的接口即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM