2016-02-13 18 views
3

逆變方法給出像下面的情況:在此代碼調用Java中

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中如何實現重寫的意外結果? ?

+1

等什麼?在你提供的例子中,'A.implementation'實際上從來沒有被調用過。 – radoh

+0

我想知道你是如何得到這個結果「*(新B())。實現(derivedObject); /例1:**調用A.implementation ***」..類A和B不在層次結構中。所以,你說的是不可能的..可能你沒有提供正確的代碼.. – hagrawal

+0

對不起,忘了提 - B延伸A.^_ ^編輯了這個帖子來修復這個漏洞。 –

回答

1

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 { 
} 

new B().implementation(new Derived()); 

這個編譯後的代碼不會改變它的行爲,如果您稍後向B提供的方法提供了向後兼容性。

0

首先,您應該可以重寫一個方法並接受更一般的參數(類似於您可以重寫某個方法並返回更多類型的特定事實)。

但是,這會給語言帶來很大的複雜性。例如,

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

所以規則就是爲了覆蓋一個方法,你必須有相同的參數列表。 (在某些情況下,如果參數列表不相同,但擦除次數相同)。準確的定義給出here