当涉及内部类时,Javainheritance如何工作

当内部类存在时,我无法理解inheritance在Java中的工作原理。 我正在研究一个子类需要稍微改变它的父类内部类的function的东西。 我在下面提出了一个更简单,更讽刺的例子。

我希望这段代码打印“我是一个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(); } } 

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

在你的调用中,你期望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)

删除重新声明

 InnerClass x; 

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

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

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

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

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

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

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