2010-03-10 63 views
29

考慮,我有以下接口:Java接口和返回類型

public interface A { public void b(); } 

不過,我希望每個實現它的類來對B法不同的返回類型()。

例子:

public class C { 
    public C b() {} 
} 

public class D { 
    public D b() {} 
} 

我如何定義我的界面,使這是可能的嗎?

回答

45

如果返回類型必須是實現該接口的類的類型,那麼你想要什麼叫做F-bounded type

public interface A<T extends A<T>>{ public T b(); } 

public class C implements A<C>{ 
    public C b() { ... } 
} 

public class D implements A<D>{ 
    public D b() { ... } 
} 

在口頭上,A正在申報一個類型參數T,將採取上實現A的每個具體類型的值。這通常用於聲明諸如clone()copy()這些類型正確的方法。又如,java.lang.Enum使用它來聲明每個枚舉的繼承的compareTo(E)方法僅適用於該特定類型的其他枚舉。

如果您經常使用此模式,則會遇到需要thisT類型的場景。乍一看,它似乎很明顯,它是,但你實際上需要聲明一個abstract T getThis()方法,實施者將不得不簡單地實現爲return this

[1]正如評論者指出的那樣,如果XY合作正確,就可以做一些偷偷摸摸的工作,如X implements A<Y>T getThis()方法的存在使得它更加清晰,X正在規避A接口的作者的意圖。仿製藥。

+0

+! - 非常好。我在這裏學到了東西。謝謝,馬特。 – duffymo 2010-03-10 01:41:47

+0

題外話:這樣的語法就是爲什麼我盡我所能避免儘可能地創建基本的API。 – dimitarvp 2010-03-10 09:17:13

+1

好的答案(以及泛型功能的一個很好的例子),但是這並不妨礙程序員執行C implements A (請參閱我的第二個答案)。 – Cam 2010-03-10 22:32:02

34

仿製藥。

public interface A<E>{ 
    public E b(); 
} 

public class C implements A<C>{ 
    public C b(){ 
     return new C(); 
    } 
} 

public class D implements A<D>{ 
    public D b(){ 
     return new D(); 
    } 
} 

搜索了仿製藥的更多細節,但(很)基本上,發生的事情是,A離開E的類型到實施clases(CD)。

所以基本上A不知道(也不必知道)在任何給定的實現中E可能是什麼。

+3

我比那個被標記爲「答案」的人更喜歡那個,因爲你不必依賴於這樣的事實:實現者實際上將他們的類名包含在基因化的聲明中。大拇指從我那裏。 – dimitarvp 2010-03-10 09:18:14

+0

這適用於任何返回類型 – 2015-11-12 15:01:13

2

由於Java supports covariant return types(因爲Java 1.5中),你可以這樣做:

public interface A { public Object b(); } 
+7

不好。你希望你的界面留下儘可能小的誤用空間。用這樣的方法,程序員在執行'A'時會犯錯誤。 – Cam 2010-03-10 01:37:07

+0

該問題沒有明確指定對重寫類型的任何限制。當然,如果存在這樣的限制,應該在可行的情況下使用界面強制執行。 – meriton 2010-03-11 00:10:15