我有以下代码:
package testapp;
class Calculation {
public Calculation(){}
public void addition(int x, int y) { }
public void Subtraction(int x, int y) { }
}
class My_Calculation extends Calculation {
public My_Calculation(){}
public void multiplication(int x, int y) { }
}
public class TestApp {
public static void main(String[] args) {
int a = 20, b = 10;
My_Calculation demo = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);
demo.multiplication(a, b);
System.out.println(demo.getClass().getName());
Calculation d = new Calculation();
d.Subtraction(b, b);
d.addition(b, b);
// no multiplication
System.out.println(d.getClass().getName());
Calculation d2 = new My_Calculation();
d2.Subtraction(b, b);
d2.addition(b, b);
// no multiplication
System.out.println(d2.getClass().getName());
}
}
输出是这样的:
demo = testapp.My_Calculation
d = testapp.Calculation
d2 = testapp.My_Calculation
下面的语句是引用变量名d2到对象类型计算的声明:
Calculation d2;
以下语句是调用 My_Calculation 构造函数的初始化。
Calculation d2 = new My_Calculation();
当我运行以下代码时,输出表明 d2 属于类类型 My_Calculation 但可以访问 Calculation 类 中的方法.
System.out.println(d2.getClass().getName());
输出:testapp.My_Calculation
访问:加法;减法
现在,我的理解告诉我,如果调用 My_Calculation 构造函数,我应该:
<强>1。仅访问乘法,或
<强>2。访问加法、减法和乘法。
但是,我实际上得到了相反的结果:只能访问加法和减法。因此,我认为这是违反直觉的。
有人可以向我解释这里发生了什么,让我对为什么类型:My_Calculation 的对象无法访问其自己的方法 但可以访问只有父类(super class)方法。
最佳答案
这里:
Calculation d2 = new My_Calculation();
您创建了一个 My_Calculation
类型的对象,但是您将它分配给了一个用父类(super class)型声明的变量!而且编译器不够聪明,无法“看到”d2
实际上是子类型。因此,编译器 会阻止您调用在该子类型上定义的方法。因为对于编译器来说,d2
被认为是一个Calculation
!
请注意,您可以转换 告诉编译器“我知道得更多”:
( (My_Calculation) d2) ).multiplication(...
这在编译时和运行时都有效!
你的误解从这里开始:
Calculation d2 = new My_Calculation();
你在作业的右侧所做的基本上会在下一行中“忘记”。然后编译器只知道你有一些计算
类型的d2
!
最后:是的,在您的特定 示例中,编译器可以轻松确定d2
的真实 类型。但在很多情况下,这并不容易,甚至不可能。因此,Java 背后的人们决定忽略这种潜在的“知识”。
关于java - 对象初始化 - 构造函数与类类型和方法访问的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56348434/