2014-04-14 34 views
1

我正在考慮編程接口而不是具體的類,但我有一個疑問:任何接口方法應該能夠保存對具體類的引用嗎?引用具體類作爲參數的接口方法會導致耦合?

假設以下情況:

1)

public interface AbsType1 { 
    public boolean method1(int a); // it's ok, only primitive types here 
} 

2)

public interface AbsType2 { 
    public boolean method2(MyClass a); // I think I have some coupling here 
} 

我應該在這裏選擇不同的設計,以避免後者?例如

public interface MyInterface {} // yes, this is empty 

public classe MyClass implements MyInterface { 
    // basically identical to the previous "MyClass" 
} 


public interface AbsType2 { 
    public boolean method2(MyInterface a); // this is better (as long as the 
              // interface is really stable) 
} 

但還是有些東西不能說服我......我覺得不自在地聲明一個空的界面,儘管我看到別人這樣做。 也許和抽象類在這裏會更好?

我有點困惑。

編輯:

好吧,我會盡量通過做一個例子更具體。比方說,我desining一個詢盤,我當然要對項目添加到購物車:

public interface ShopCart { 
    public void addArticle(Article a); 
} 

現在,如果文章是一個具體的類,如果其實現隨時間的變化?這就是爲什麼我可以考慮將它作爲一個接口,但是再一次說,它可能不適合至少在語義層面上,因爲接口應該指定行爲,而Article沒有(或者幾乎沒有......)我想這是一種實體類)。

因此,我現在可能會得出這樣的結論:在這種情況下將Article作爲一個抽象類將是最好的事情......您怎麼看待它?

+1

我可以看到事情還行 –

+0

爲什麼你聲明你的接口是空的? AbsType'關心的'MyClass'中沒有任何相關的公共方法嗎? - 如果沒有,那麼也許你最好使用類的泛型。 – JimmyB

回答

1

在我看來,Interfaces適用於實施可能會有所不同的所有類型。但是如果你定義了一個module,它引入了一個新類型,而不是有另外的實現,那麼不需要首先將它定義爲Interface。在我看來,這往往是過度設計。它取決於問題領域,並且經常依賴於如何進行支持測試或AOP編織。

例如,考慮一個2D問題域,您需要將Location作爲類型進行建模。如果確定Location總是由xy座標表示,則可以將其作爲Class提供。但是,如果您不知道Location可能具有哪些屬性(GPS數據,x,y,z座標等),但是您依賴某些行爲(如distance()),則應該將其作爲接口進行建模。

+0

感謝這個答案,這是非常清楚:) – tmh

2

我會使用接口,因爲組合比繼承好得多。 「任何接口方法應該能夠持有對具體類的引用?」,爲什麼它不應該?包內的一些類是耦合的,這是一個事實和常用的技術。當你在接口中標記這個關係時,你會發現哪些類依賴於你的實現。依賴或組合關係不是繼承,所以我會避免抽象類。

+0

我增加了一個例子...在這種具體情況下,你會避免抽象類以及?你會怎麼做? – tmh

+0

我們同樣思考,我也會做文章摘要,這顯然是繼承關係,但ShopCart指定行爲,它對實體Article有效,所以它應該是接口。 –

1

如果沒有公共方法AbsType將在MyClass訪問,那麼空接口可能不是一個好方法。

沒有靜態方法的接口聲明(契約),否則在這裏可能是有意義的。因此,如果AbsType不打算使用MyClass/MyInterface中的任何方法,那麼我認爲它基本上只存儲用於其他目的的類對象。在這種情況下,可以考慮使用泛型來明確你想怎麼AbsType是沒有緊密連接到客戶端的代碼中使用,如

public class AbsType3<C extends Class<?>> { 

    public boolean method3(T classType) {...} 

} 

然後,你可以限制類型的類,允許在需要時通過交換<C extends Class<?>>類型參數也可能是一個接口,如 <C extends Class<Collection<?>>>

空接口有點像類的布爾標誌:一個類實現接口(true)或不接受(false)。如果有的話,這些標記界面應該用於傳達關於如何使用類(或不被使用)的重要陳述,例如參見Serializable

+0

我提供了一個例子......在這種情況下,我認爲沒有必要使用泛型。你怎麼看? – tmh

+0

你說得對。所以如果你想實際使用傳遞給你的方法的對象,你可以使用任何接口,抽象類或具體類的方法。爲了儘量減少耦合,我實際上推薦使用一個接口。當然,一個接口不能像一個具體的實現那樣執行一個合約,但如果接口是精心設計的,這不一定是個問題。 Otoh,只要你在你的(抽象)基礎實現中不使用final方法,那麼也沒有辦法強制執行一個合同;任何方法都可能被違反合同的行爲所覆蓋。 – JimmyB

+0

轉到界面。 – JimmyB