2013-09-26 68 views
1

我一直在研究空接口和抽象類,從我讀過的內容來看,它們通常是不好的做法。我打算將它們用作我撰寫的小型搜索應用程序的基礎。我會寫最初的搜索提供者,其他人也可以創建他們自己的提供者。我的代碼的意圖是強制任何人想要實現它們的類之間的關係。空接口和抽象類實施結構

有人可以叮叮噹噹地描述是否以及爲什麼這仍然是一個不好的做法,以及如果有任何替代方法可用。

namespace Api.SearchProviders 
{ 
    public abstract class ListingSeachResult 
    { 
     public abstract string GetResultsAsJSON(); 
    } 

    public abstract class SearchParameters 
    { 
    } 

    public interface IListingSearchProvider 
    { 
     ListingSeachResult SearchListings(SearchParameters p); 
    } 
    } 
+0

這可能更適合於http://codereview.stackexchange.com/ –

+4

什麼是空類會有用?它完全沒用。刪除它,讓你的方法期待一個「對象」。 –

+1

你打算如何在'SearchListings'中使用'p'?你確定你不想在這個空白的界面/類中有東西嗎?如果你真的這樣做,我會用一個空的接口去做,而不是一個空的抽象類,這樣你仍然可以選擇繼承別的東西。 –

回答

1

空的類和接口通常只是「可用的」作爲通用約束;這些類型本身並不可用,通用約束通常是唯一可以將其與其他有用的結合使用的上下文。例如,如果IMagicThing封裝了一些值,一些實現是可變的,有些是沒有,這要記錄與IMagicThing關聯的值類似的方法可以寫成:

void RecordValues<T>(T it) where T:IImagicThing,IIsImmutable {...} 

其中IIsImmutable是一個空接口的合同說任何實現它併爲任何財產報告一些價值的類都必須永遠更多地報告該財產的相同價值。按指示書寫的方法可以知道其參數在合同中有義務表現爲IMagicThing的不可變實現。

從概念上講,如果接口的各種實現將對他們的行爲做出不同的承諾,那麼能夠將這些承諾與約束結合起來似乎很有幫助。不幸的是,這種方法存在一個相當討厭的限制:除非知道滿足所有約束的特定類型以及從哪個對象派生出來,否則不可能將對象傳遞給上述方法。如果只有一個約束,則可以將該對象轉換爲該類型,但如果有兩個或更多個,則該方法無效。

由於使用約束泛型當上述困難的,這是更好地表達「一個IMagicThing這將是不可改變的」通過定義從IMagicThing派生,但沒有增加新成員的接口IImmutableMagicThing的概念。期望IImmutableMagicThing的方法不會接受任何不實現不可變接口的IMagicThing,即使它碰巧是不可變的,但如果有一個IMagicThing的引用實現了IImmutableMagicThing,那麼可以將該引用強制轉換爲後一種類型並將其傳遞給需要它的例程。

順便提一下,我可以看到一個空類類型的其他用法:作爲身份標記。一個類不需要任何成員作爲字典鍵,監視器鎖或弱引用的目標。特別是如果有一個與這種用法相關的擴展方法,爲此目的定義一個空類可能比使用Object方便得多。