2013-07-18 33 views
3

我工作的一個項目具有以下(非常簡單的)結構:接口修復遺傳混亂?

BaseClass 

SubClassA : BaseClass 
SubClassB : BaseClass 

有一個UI(有很多邏輯的),它採用SubClassA,然後將其保存到這需要BaseClass另一個組件作爲參數,但立即將參數轉換爲SubClassB。這在UI傳入SubClassA時失敗。

UI:

MyComponent.Save(subClassA) 

Component: 
Save(BaseClass baseClass) 
{ 
SubClassB subClassB = (SubClassB)baseClass; 

...

目前執行的UI創建SubClassB的實例,並通過跨 - 但它會導致大量的代碼,如

SubClassB.Property1 = SubClassA.Property1a 

我正在考慮創建一個2子類將實現的通用接口。這將是很多工作,但慢慢地我認爲我可以將目前非常深的層次結構扁平化。重構UI或組件以使用其他子類型與結構不同(儘管許多字段映射)一樣多。界面的方法是否正確?我覺得可能有一些我錯過了。

+0

我看不到接口會在這裏幫助...爲什麼不修復保存方法?它應該將SubClassB作爲參數或者應該正確支持BaseClass。 – LightStriker

+0

@LightStriker - 如果我更新保存以獲取SubClassB,我仍然有從UI轉換到subclassB實例的問題。不幸的是,基類沒有太多的子類的細節,我的想法是一個接口將是跨多個組件的更一致的交互的起點(繼承是一個混亂...) – NDJ

回答

2

如果SubclassASubclassB通過自己的能力不僅關係到Save,那麼,BaseClass將作爲兩個子類實現一個接口更好。

它不會立即解決您的直接問題:將組件從基類轉換爲(錯誤的)派生類。看起來這裏可能有幾個級別的重構。修補代碼,以便通過爲其使用一個組件來鑄造到SubclassA是浪費的,我想。改變組件以便它可以在一種單一的通用類型上運行將是一個很大的勝利。

展平深層次結構也會帶來很多其他好處 - 比如簡化它。如果最終成爲他們都實現的一些接口,那不一定是壞事。但是,請注意包中包含大量的接口類型。

簡而言之,對UI和組件以及任何其他代碼都進行重新編譯,只使用少量的接口,而無需瞭解實現類,將會帶來收益。

+0

它是與其說是存儲能力與類有關,不如說是它們的屬性(它們非常相似) - 我同意拼合和重構將是一個巨大的勝利。出於好奇,你能解釋'打包的界面類型'嗎? – NDJ

+0

@NDJ - 創建大量非常小的接口可以提供細粒度的功能(比如「ISave」,「ILoad」 - 你明白這個想法),而不是捕捉真正的抽象。我想我的意思是,如果你發現自己需要實現大量的接口,並且在幾個實現類中有一個常見的「包」,它通常是一個指示器,可以找到更高級別的抽象。 – SteveLove

1

爲什麼不在基類中創建一個Save()virtual - 這看起來是一個更好的選擇。這樣,如果您有任何常用的保存功能,您可以使用它並在派生類中爲其提供其他形式 - 稱爲polymorphism

class BaseClass 
{ 
    public virtual void Save() 
    { 
    //Use this keyword 
    } 
} 
class B : BaseClass 
{ 
    public override void Save() 
    { 
    base.Save(); 
    } 
} 
2

消費者的角度來看,接口幾乎可以做抽象類可以做的所有事情(主要的例外是類可以將字段暴露爲byref,而接口無法這樣做,而靜態成員與一個類關聯的類可以在類名下進行分組,與接口相關的靜態成員必須以不同的名稱分組)。除了需要將字段公開爲byref的罕見情況外,抽象類的主要優勢來自實現方面。所有與接口相關的功能都必須在實現它的每個類中單獨提供,即使這樣的功能在實現它的類的99%中通用。相比之下,如果從抽象類派生的具體類的99%將以同樣的方式實現特定的方法,則抽象類可以定義該方法一次,並讓派生類繼承它,而不必爲此付出任何代價。這樣的好處可以很好,但是有一個主要的問題:一個類只能繼承另一個類的功能。由於接口不包含任何功能,因此它們可以從許多其他類繼承。

當我們定義一個抽象類時,我會建議應該在很多情況下定義一個包含相同公共功能(抽象類應該實現)的接口,並避免使用抽象類的變量或參數類型。這將允許可以從抽象類繼承的實現來實現這樣做會帶來的易於實現的好處,但也可以定義從其他事物繼承的實現。編寫一個從其他類型繼承的實現將會是更多的工作,但是如果代碼從未在變量,字段或參數聲明中使用抽象類類型,那麼使用抽象類的派生類的代碼將與接口實現一樣好別。

+0

+1 - 但還注意到實現接口不會「用盡」您的單一繼承配額 – SteveLove