Java联合变量返回
在java中,当非协变返回类型产生编译时错误时,为什么协变返回类型可以接受。当然,如果JVM可以处理协变返回类型,那么它就可以处理非协变返回类型。我假定,当java看到一个具有协变返回的重写方法时,它只应用与调用对象关联的方法。为什么非协变回报类型不能发生同样的情况。 我的猜测是,这与打破超类方法契约的条款有关,当然,如果允许这样做,那么子类(重写)方法的行为就不是很可预测的(因为返回类型没有一致性) 这里有一个例子(假设狗粮是食物的一个子类,但猫粮不是食物的一个子类): 动物类Java联合变量返回,java,return-type,covariant,Java,Return Type,Covariant,在java中,当非协变返回类型产生编译时错误时,为什么协变返回类型可以接受。当然,如果JVM可以处理协变返回类型,那么它就可以处理非协变返回类型。我假定,当java看到一个具有协变返回的重写方法时,它只应用与调用对象关联的方法。为什么非协变回报类型不能发生同样的情况。 我的猜测是,这与打破超类方法契约的条款有关,当然,如果允许这样做,那么子类(重写)方法的行为就不是很可预测的(因为返回类型没有一致性) 这里有一个例子(假设狗粮是食物的一个子类,但猫粮不是食物的一个子类): 动物类 public
public class Animal {
public Food seekFood() {
return new Food();
}
}
犬类
public class Dog extends Animal {
public DogFood seekFood() { //This is OK since its a covariant
return new DogFood();
}
}
猫类
public class Cat extends Animal {
public CatFood seekFood() { // This won't compile. Catfood is not covariant
return new CatFood();
}
}
如果两个方法具有相同的签名(方法名和参数类型),编译器将无法决定选择调用哪个方法。如果两个方法具有相同的名称,但参数类型和返回类型不同-它们具有不同的签名,那么编译器可以选择调用哪一个 更新: javac将协变量方法编译成它的基类方法,当您调用它时,基类方法将调用委托给子类方法。因为它们返回不同的类型,所以不能进行类型转换。多亏了,这个过程可以用一个代码片段解释得非常清楚:
class CircleFactory extends ShapeFactory {
public Circle newShape() {
// your code from the source file
return new Circle();
}
// javac generated method in the .class file
public Shape newShape() {
// call the other newShape method here -- invokevirtual newShape:()LCircle;
}
}
继承规则决定共变/反变行为:
类型T的值只能分配给类型T或父类型的变量。
方法调用意味着将其实际方法参数(1)分配给局部参数(2),并将结果值(1)分配给要使用的某些位置(2)
现在,如果编译器遇到了一个实际上可以是A B的A对象,那么B.f
就是一个有效的覆盖:
B.f
必须返回可分配给Ra的内容在本案中,当狗粮是食物的孩子时,猫可能会退回狗粮。因此,任何动物的食物实际上都是食物,即使动物实际上是一只猫。我实际上没有理解你的意思。。这可能是个好问题,但请举例说明。。在我的例子中,这三种方法都有相同的签名。但是,它们都有不同的返回类型。对于协变函数,编译器不会抱怨,并且可以选择调用哪个方法;它根据对象类型确定要调用的方法。在Cat示例中,Catfood不是食物的协变变量,因此Cat的seekFood方法不会编译。为什么呢?我怀疑JVM可以将其视为协变变量,但如果它这样做,那么我猜您将拥有不可预测/紧密耦合的代码?
class A {
Ra f(Pa x) { ... }
}
class B extends A {
@Override
Rb f(Pb x) { ... }
}