为什么我不能更改覆盖方法的 return 类型(协变 return 类型除外)?
Why can't I change the return type of overriden methods (other than covariant return type)?
请注意 - 我在问为什么?如果您能给出一个示例,其中更改 return 类型实际上会破坏代码
,那将非常有用
为什么我不能更改重写方法的 return 类型(协变 return 类型除外)。
class Parent{
public void sayhello(){ ... };
}
class Child extends Parent{
public String sayhello() { . . .}
}
现在如果我运行下面的代码:
class test{
public static void main(String[] args){
Parent p = new Child();
p.sayHello();
}
}
摄像头请确认以下步骤是否正在发生:
- 编译器找出对象的类型 'p' 是 Parent。
编译器检查父 class 中是否存在方法 'sayHello()'。
在运行时,JVM 发现它是一个子对象并调用该方法的子版本。
- 子方法被调用。
谢谢。
让我们用一个简单的例子来解释为什么 any 改变被覆盖方法的 return 类型没有意义。
假设我有一个 Car
对象:
class Car {
public String getModel() {
return "Awesome Car";
}
}
这个 Car
class 有一个方法 getModel()
return 是 String
.
现在,您有另一个 class 扩展 Car
并覆盖 getModel()
方法:
class DumbCar extends Car {
@Override
public Hamburger getModel() {
return new Hamburger();
}
}
突然之间,你遇到了一个大问题。您创建了一个 DumbCar
对象,因为您知道所有 Car
对象都可以告诉您它们的模型,您尝试 get 该模型:
DumbCar myCar = new DumbCar();
System.out.println(myCar.getModel());
输出为A juicy Big Mac!
你觉得这有意义吗?你不能开大 Mac。
Java 是一种重 type-safe 的语言。当你写一个请求 getModel()
的语句时,你需要绝对地 100% 肯定你得到的数据是你所期望的。 Java 强化了这种期望。
Java 是一种静态类型语言。
这意味着编译器会在程序 运行 之前检查所有类型是否有意义。所以你不会在 运行 时得到错误,因为某些方法或字段不是 "there".
如果您的代码显示
,则为了使它起作用
MyBean x = something.getMyBean();
不允许编译器确定 something
类型的子类将 getMyBean()
的 return 类型更改为 [=13 以外的类型=](也允许 MyBean
的子类,这称为缩小 return 类型——但即使在 Java 5 之前这也是不可能的。
问题基本上是这样的事情会使 Java 类型系统不健全,并且由于 Java 有一个 statically-typed 系统,这是不允许的。
假设您有一个 Expression
接口:
interface Expression {
Integer evaluate();
}
现在您有了 Addition
实施:
class Addition implements Expression {
private Expression left;
private Expression right;
Addition(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public Integer evaluate() {
return left.evaluate() + right.evaluate();
}
}
只要表达式的计算结果为整数,这就有效,例如
class Constant implements Expression {
private Integer value;
Constant(Integer value) {
this.value = value;
}
@Override
public Integer evaluate() {
return this.value;
}
}
这让我们可以做如下事情:
Expression left = new Constant(1);
Expression right = new Constant(2);
Expression addition = new Addition(left, right);
Integer result = addition.evaluate();
如果您有一个表达式,而不是计算为 Integer
,计算为其他不是表达式的东西,例如 Cat
或 Dog
,现在会发生什么?
它会立即破坏您过去编写的所有其他表达式的可靠性,例如上一个示例或我们在 Addition.evaluate
方法中所做的明显假设,我们假设 left
right
表达式返回 Integer
而不是 Cats
或 Dogs
.
请注意 - 我在问为什么?如果您能给出一个示例,其中更改 return 类型实际上会破坏代码
,那将非常有用为什么我不能更改重写方法的 return 类型(协变 return 类型除外)。
class Parent{
public void sayhello(){ ... };
}
class Child extends Parent{
public String sayhello() { . . .}
}
现在如果我运行下面的代码:
class test{
public static void main(String[] args){
Parent p = new Child();
p.sayHello();
}
}
摄像头请确认以下步骤是否正在发生:
- 编译器找出对象的类型 'p' 是 Parent。
编译器检查父 class 中是否存在方法 'sayHello()'。
在运行时,JVM 发现它是一个子对象并调用该方法的子版本。
- 子方法被调用。
谢谢。
让我们用一个简单的例子来解释为什么 any 改变被覆盖方法的 return 类型没有意义。
假设我有一个 Car
对象:
class Car {
public String getModel() {
return "Awesome Car";
}
}
这个 Car
class 有一个方法 getModel()
return 是 String
.
现在,您有另一个 class 扩展 Car
并覆盖 getModel()
方法:
class DumbCar extends Car {
@Override
public Hamburger getModel() {
return new Hamburger();
}
}
突然之间,你遇到了一个大问题。您创建了一个 DumbCar
对象,因为您知道所有 Car
对象都可以告诉您它们的模型,您尝试 get 该模型:
DumbCar myCar = new DumbCar();
System.out.println(myCar.getModel());
输出为A juicy Big Mac!
你觉得这有意义吗?你不能开大 Mac。
Java 是一种重 type-safe 的语言。当你写一个请求 getModel()
的语句时,你需要绝对地 100% 肯定你得到的数据是你所期望的。 Java 强化了这种期望。
Java 是一种静态类型语言。
这意味着编译器会在程序 运行 之前检查所有类型是否有意义。所以你不会在 运行 时得到错误,因为某些方法或字段不是 "there".
如果您的代码显示
,则为了使它起作用MyBean x = something.getMyBean();
不允许编译器确定 something
类型的子类将 getMyBean()
的 return 类型更改为 [=13 以外的类型=](也允许 MyBean
的子类,这称为缩小 return 类型——但即使在 Java 5 之前这也是不可能的。
问题基本上是这样的事情会使 Java 类型系统不健全,并且由于 Java 有一个 statically-typed 系统,这是不允许的。
假设您有一个 Expression
接口:
interface Expression {
Integer evaluate();
}
现在您有了 Addition
实施:
class Addition implements Expression {
private Expression left;
private Expression right;
Addition(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public Integer evaluate() {
return left.evaluate() + right.evaluate();
}
}
只要表达式的计算结果为整数,这就有效,例如
class Constant implements Expression {
private Integer value;
Constant(Integer value) {
this.value = value;
}
@Override
public Integer evaluate() {
return this.value;
}
}
这让我们可以做如下事情:
Expression left = new Constant(1);
Expression right = new Constant(2);
Expression addition = new Addition(left, right);
Integer result = addition.evaluate();
如果您有一个表达式,而不是计算为 Integer
,计算为其他不是表达式的东西,例如 Cat
或 Dog
,现在会发生什么?
它会立即破坏您过去编写的所有其他表达式的可靠性,例如上一个示例或我们在 Addition.evaluate
方法中所做的明显假设,我们假设 left
right
表达式返回 Integer
而不是 Cats
或 Dogs
.