Java中逆变方法的调用
考虑到如下情况:Java中逆变方法的调用,java,oop,contravariance,Java,Oop,Contravariance,考虑到如下情况: interface Base { } interface Derived extends Base{ } interface OtherDerived extends Base{ } class A { void implementation(Derived stuff) { // Implementation A } } class B extends A { // contravariant; does not override
interface Base { }
interface Derived extends Base{ }
interface OtherDerived extends Base{ }
class A {
void implementation(Derived stuff) {
// Implementation A
}
}
class B extends A {
// contravariant; does not override
void implementation(Base stuff) {
// Implementation B
}
}
此代码中的方法调用按如下方式调度:
(new B()).implementation(derivedObject); // Ex. 1: calls A.implementation
(new B()).implementation(baseObject); // Ex. 1: calls B.implementation
(new B()).implementation(otherDerivedObject()); // Ex. 2: calls B.implementation
我一直想知道的是,为什么Java将逆变方法(B.implementation)本质上视为重载(除了A.implementation和B.implementation的签名不是等价的)。是否有一个有意的理由分派到最具体的方法签名(如果有,您能告诉我在Java规范中明确说明了这一点吗?),或者,这仅仅是Java中如何实现重写的意外结果?Java从其父级继承所有方法,除非它们已被重写或隐藏。这意味着您的
B
类与
class A {
void implementation(Derived stuff) {
// Implementation A
}
}
class B extends A {
// contravariant; does not override
void implementation(Base stuff) {
// Implementation B
}
void implementation(Derived stuff) {
super.implementation(stuff);
}
}
这样做的好处是说你有
class A {
void implementation(Derived stuff) {
// Implementation A
}
}
class B extends A {
}
及
如果您以后向B添加一个方法以提供向后兼容性,则编译后的代码不会改变其行为。起初,您可能会发现您应该能够重写一个方法并接受更一般的参数(类似于您可以重写一个方法并返回更具体的类型) 然而,它会给语言带来极大的复杂性。比如说,
class A {
void foo(String s) {}
}
class B extends A {
void foo(CharSequence s) { System.out.println(true); }
void foo(Serializable s) { System.out.println(false); }
}
有了你的提议,这本书应该印什么
A a = new B();
a.foo("bar");
所以规则很简单,为了覆盖一个方法,你必须有相同的参数列表。(在某些情况下,当参数列表不相同,但具有相同的擦除时,可以重写)。给出了精确的定义 等等什么?在您提供的示例中,
A.implementation
实际上从未被调用。我想知道您是如何得到这个结果的“(new B()).implementation(derivedObject);//例如1:调用A.implementation”。。A类和B类不在层次结构中。。所以,你说的是不可能的。。可能你没有提供正确的代码。呵呵,对不起,忘了提到-B扩展A。^ ^编辑了这篇文章以修正遗漏。我想他的意思是B扩展A
。否则,这个问题就没有意义了。@exception1我认为OP是对的。。如果A扩展了B
,那么这个问题就没有意义了。。
A a = new B();
a.foo("bar");