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

时间:2017-05-30 15:08:58

标签: java override protected

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

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。但我仍然不明白为什么会出现这个问题。

2 个答案:

答案 0 :(得分:1)

你要做的是打败多态的目的。你可以,但你必须专门打电话。在方法中添加一个布尔值并调用super.initialize(Boolean)。同样,这会破坏多态性和扩展类HAS以了解超类。不是很优雅。

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

  }

答案 1 :(得分:0)

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

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

以下是问题的答案 - 这种情况发生了,因为我们只为B实例分配了内存,这意味着我们将A作为 base 并启动了扩展它(我们可以覆盖里面的任何东西)。我们做的唯一两件事是:

  1. 我们创建了一个构造函数(它不包含在 base 中,如上所述)
  2. 我们覆盖了initialize方法代码。现在,此对象的 base 中的此方法的代码已丢失。
  3. polymorphism这个概念就是这样设计的,除非我们专门创建一个A本身的对象,否则我们无法访问 base 方法。一个不会覆盖这种方法的孩子。