为什么从基class调用方法会调用子方法?
Why does calling a method from base class calls the child method?
我是一名学生,正在学习Java。我知道,protected
表示从 children
或 the 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 并开始扩展它(虽然我们可以覆盖里面的任何东西)。我们只做了两件事:
- 我们创建了一个构造函数(如上所述,它没有包含在 base 中)
- 我们覆盖了
initialize
方法代码。对于此对象,base 中的此方法的代码现已丢失。
这个 polymorphism
的概念就是这样设计的,我们无法访问 base 方法,除非我们专门创建一个对象 A
本身或不覆盖此方法的子项。
我是一名学生,正在学习Java。我知道,protected
表示从 children
或 the 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 并开始扩展它(虽然我们可以覆盖里面的任何东西)。我们只做了两件事:
- 我们创建了一个构造函数(如上所述,它没有包含在 base 中)
- 我们覆盖了
initialize
方法代码。对于此对象,base 中的此方法的代码现已丢失。
这个 polymorphism
的概念就是这样设计的,我们无法访问 base 方法,除非我们专门创建一个对象 A
本身或不覆盖此方法的子项。