2012-05-14 53 views
3

只是玩弄接口,我有一個我不能理解的東西的問題。Java - 接口方法

以下代碼不運行,這是我期望的行爲,因爲接口方法要求該方法適用於任何對象,並且實現的方法將簽名更改爲僅允許字符串對象。

interface I { 
    public void doSomething(Object x); 
} 

class MyType implements I { 
    public void doSomething(String x) { 
     System.out.println(x); 
    } 
} 

但是,使用下面的代碼塊,我很震驚地看到,它的工作。 我認爲它不會工作,因爲我們期望返回一個對象,並且實現的方法將只返回一個字符串對象。爲什麼這個工作以及傳遞參數和返回類型的兩個原則有什麼區別?

interface I { 
    public Object doSomething(String x); 
} 

class MyType implements I { 
    public String doSomething(String x) { 
     System.out.println(x); 
     return(x); 
    } 
} 

回答

3
public Object doSomething(String x); 

有返回的東西。事實上,只要它是某種類型的對象。所以如果你執行

public String doSomething(String x) {stuff} 

這很好,因爲它確實返回一個對象。它將返回的對象始終是一個字符串的事實沒有什麼大不了的。

第一個示例不起作用的原因是因爲只接受字符串比接受任何對象更受限制。但只返回字符串很好。

作爲一個比喻,假設你有一份合同來繪製建築物,而且你會僱傭一些員工來幫助你。合同要求您僱用適用的任何畫家,不管他們多高,但不指定使用什麼顏色的油漆。如果你只僱用6英尺高的畫家(這是輸入,只接受字符串而不是所有對象),那麼你就違反了合同。但選擇只用藍色油漆(僅返回字符串)進行繪製就好了,因爲合同沒有指定顏色,只是必須繪製建築物。

2

它的工作原理,因爲StringObject

+1

那麼這不是真的在這裏的答案。他的第一個例子具有相同的「演員」。第二次工作的原因由maress – keyser

+0

解釋。他的第一個例子中沒有演員。該接口聲明一個將對象作爲參數的方法。有一個接受一個字符串的方法與獲取一個對象不一樣。你可以傳遞一個Integer到他的字符串方法,就像你可以使用一個接受Object的方法嗎? –

+0

這更多的是一個答案,但還不是那裏:第 – keyser

2

從Java語言規範:

返回類型可重寫彼此如果返回類型是引用類型的方法而異。 return-type-substitutability的概念支持協變返回,即返回類型專用於子類型。

換句話說,它可以像你一樣工作,但如果接口中的返回類型是字符串,並且在實現類中是Object,它將不起作用。

1

第一個示例不起作用,第二個示例的原因是函數原型僅由名稱和所有參數定義,而不是返回類型。在第一個例子中,有一個區別,所以編譯器認爲它們是兩個不同的函數。

在第二個示例中,實現的函數不擴展類型,而是專門化類型(String是Object的專門化),因此它可以工作。

同樣,您可以限制實施方法的可見性,但不能擴大它。

此外,Java具有泛型,在此上下文中非常有用。

實施例:

interface I<T> 
{ 
    public void doSomething(T x); 
} 

class MyType implements I<String> 
{ 
    public void doSomething(String x) 
    { 
     System.out.println(x); 
    } 
} 
1

方法簽名不考慮返回類型。 (雖然聲明兩個具有相同簽名但返回類型不同的方法是錯誤的)。所以:

void doSomething(Object) 
void doSomething(String) 

只不過是兩種方法並沒有覆蓋或實現其他

2

此行爲背後的原理稱爲covariant return type。在這種特殊情況下,覆蓋類型可能會「縮小」最初聲明的參數類型。

這意味着,如StringObject的子類,Object可能被String替代。

1

字符串類是從對象類繼承的,所以只有這個代碼有效。