为什么从基class调用方法会调用子方法?

Why does calling a method from base class calls the child method?

我是一名学生,正在学习Java。我知道,protected 表示从 childrenthe same package 访问。这里我们继承并覆盖了一个受保护的方法。在这样的操作之后,每当基 class 想要调用它自己的方法时,它会调用子 class 中新的被覆盖的方法。我已经调试了一段时间,并用注释标记了执行顺序。但是我不明白为什么当我从 base class 构造函数内部清楚地调用它时它不调用 base 方法?

public class Solution {

    public static void main(String[] args) {
        new B(); // first
    }

    public static class A {

        public A() {
            initialize(); // third
        }

        protected void initialize() {
            System.out.println("class A"); // we never go here
        }
    }

    public static class B extends A {

        public B() {
            super(); // second
            initialize(); // fifth
        }

        protected void initialize() {
            System.out.println("class B"); // fourth, sixth
        }
    }
}

这是一个网站的任务,所以基本上解决方案是将 initialize 方法的访问修饰符从 protected 更改为 private。但是我还是不明白为什么会出现这个问题。

你想做的是破坏多态性的目的。可以,但你必须专门拨打电话。向您的方法添加一个布尔值并调用 super.initialize(Boolean)。同样,这打败了多态性,扩展 class 必须知道超级 class。不是很优雅。

public class Solution {
    public static void main(String[] args) {
        new B(); // first
    }

    public static class A {

    public static boolean USE_SUPER = true;

        public A() {
            initialize(USE_SUPER); 
        }

        protected void initialize(boolean unusedHere) {
            System.out.println("class A");
        }
    }

     public static class B extends A {
         public static boolean USE_EXTENDED = false;

         public B() {
            super();
            initialize(USE_EXTENDED);
         }

    protected void initialize(boolean useSuper) {
        if (useSuper)
                super.initialize(useSuper);
        else
                 System.out.println("class B");
     }
}

  }

正如 Dakoda 回答的那样,根本原因是 polymorphism。这意味着我们可以创建子对象,但将它们称为它们的父类型,当我们调用父层的方法时,我们实际上是指子对象的方法。

在我的例子中,我创建了一个子对象(标记为 //first)B,它有自己的 initialize 方法体。继承的一个细微差别是它不包含构造函数,因此我可以调用父级的构造函数(标记为//second)。在父类的构造函数中,我调用了 initialize 方法——这就是多态性,因为我从其父类抽象层调用了子类的方法。

这是问题的答案 - 发生这种情况是因为我们只为 B 实例分配了内存,也就是说,我们将 A 作为我们的 base 并开始扩展它(虽然我们可以覆盖里面的任何东西)。我们只做了两件事:

  1. 我们创建了一个构造函数(如上所述,它没有包含在 base 中)
  2. 我们覆盖了 initialize 方法代码。对于此对象,base 中的此方法的代码现已丢失。

这个 polymorphism 的概念就是这样设计的,我们无法访问 base 方法,除非我们专门创建一个对象 A 本身或不覆盖此方法的子项。