2014-09-23 133 views
3

我想在我的android項目中自動轉換視圖。所以,我想通過通過泛型方法覆蓋非泛型方法

<T extends View> findViewById(int id) {...} 

方法重寫

View findViewById(int id) {...} 

方法。但是java編譯不允許這樣做,但是重寫的方法不會與父類衝突,並且總是會返回視圖對象或其子對象。我發現了一些信息,java不允許通過泛型方法覆蓋非泛型方法,但解釋爲什麼是我找不到。

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ824 這個FAQ說這是不可能的,但我不明白爲什麼。作爲例子,我們有這樣的類:

class Super { 
    public void set(Object arg) { ... } 
    public Object get() { ... } 
} 
class Sub extends Super { 
    public <S extends Number> void set(S arg) { ... } // overloads 
    public <S extends Number> S get() { ... } // overloads 
} 

常見問題是,他們應該有超載編譯,但我有奇怪的事情: 吸氣返回相同的錯誤我findViewById,但二傳手沒有錯誤編譯。

有人能解釋我這件事嗎?爲什麼java不允許通過泛型重寫非泛型,爲什麼setter編譯,getter - no?

我知道,我可以用一些其他方法,例如

<T extends View> findView(int id){ 
    return (T) findViewById(id); 
} 

<T extends View> findView(int id, Class<T> clazz) { 
    return clazz.cast(findViewById(id)); 
} 

但我想明白了,我爲什麼要使用新的方法,而不是壓倒一切的?

//1 
@Override 
public View findViewById(int id) { 
    return (View) super.findViewById(id); 
} 
//2 
@Override 
public <T extends View> T findViewById(int id) { 
    return (T) super.findViewById(id); 
} 

那麼,在編譯期間,1和2有什麼區別?甚至方法1更一般地,大於2

//3 
@Override 
public <T extends View> View findViewById(int id) { 
    return (View) super.findViewById(id); 
} 

後我加入方法如上述,我終於實現,即「T延伸視圖」告訴編譯器,它不是相同的方法,而無需「T延伸查看」。所以,實際上,我創建了另一個新的方法,但具有相同的名稱和參數,因此無法編譯。也許這不完全正確,但正如我所理解的 - 類似於真實。

謝謝大家,誰試圖幫助我。

+0

沒有必要聲明您在簽名中不使用的類型參數。 – newacct 2014-09-24 02:13:18

+0

這是顯而易見的。我宣佈這只是爲了理解。這是我的問題第三次編輯後:) – 2014-09-24 04:55:47

回答

1

set方法Sub編譯,因爲你聲明方法稱爲set,可以採取任何參數S that extends Number。 。注意你不重寫Sub類中Super類的設置方法,你已經重載了設置方法
With get方法你正在做的完全一樣,即重載get方法,但是這次編譯器會抱怨,因爲它沒有效,因爲你改變了只是方法的返回類型。對於例如

public Object get() { 
    return null; 
} 

,並通過更改只是方法的返回類型像聲明中相同或子類的另一種方法這

public Number get() { 
     return null; 
    } 

那麼編譯器會抱怨「get()方法已經被定義」,因爲在java返回類型不是方法簽名的一部分。
如果聲明

public <S extends Number> void set(Object arg) { } 

在這種情況下,我們再次只是改變了方法的返回類型,但是是有效的重載方法的參數應該是可以複製同樣的問題對於set方法不同,所以

public <S extends Number> void set(String arg) { } // overloads 

將是一個有效的過載

+0

謝謝。最後我明白,是一個參數,它是另一種方法,所以它是一個重載,而不是重載。但它具有相同的簽名,所以它不能編譯。 – 2014-09-23 10:53:48

+0

歡迎你,如果你覺得這篇文章有用,那麼你總是可以upvote – sol4me 2014-09-23 10:55:39

+0

我需要15點的聲譽:)但我會盡我所能。 – 2014-09-23 10:59:56