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

当涉及内部类时,Java继承是如何工作的,java,inheritance,polymorphism,inner-classes,Java,Inheritance,Polymorphism,Inner Classes,当存在内部类时,我很难理解继承在Java中是如何工作的。我目前正在做一些事情,其中子类需要稍微更改其父类的内部类的功能。我在下面给出了一个更简单的例子 我希望这段代码可以打印“我是一个ChildClass.InnerClass”,但它会打印 “我是一个父类。内类”。为什么会这样?另外,如果我在main中更改obj对象 如果是ChildClass类型,则输出更改为“我是一个ChildClass.InnerClass”。为什么会这样 一般来说,改变对象父类内部对象行为的推荐方法是什么 class I

当存在内部类时,我很难理解继承在Java中是如何工作的。我目前正在做一些事情,其中子类需要稍微更改其父类的内部类的功能。我在下面给出了一个更简单的例子

我希望这段代码可以打印“我是一个ChildClass.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();
   }
}
变量不会像方法那样被“重写”

在您的调用中,您希望
x
子对象的一个,但这不是因为
x
是一个变量,而不是一个方法

但是请注意:您的引用类型是
ParentClass
,因此
obj.x
指向
ParentClass
InnerClass
属性,即使
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)

删除重新声明

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

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

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

一般来说,建议用什么方法来改变用户的行为 对象的父类的内部对象

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


这将比您建议的更灵活,因为只要有正确的接口,
newInnerClass()
就可以实例化在任何地方定义的类//obj.x表示子对象中的x
??你是指儿童班obj;如果第二个
InnerClass
扩展了
ParentClass.InnerClass
,那么它的构造函数将调用
ParentClass
构造函数。从而用ParentClass的InnerClass隐藏子类的InnerClass