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");