2011-09-28 61 views
8

我有一堆系統,我們打電話給他們A, B, C, D, E, F, G, H, I, J接口,抽象,或只是虛擬的方法?

它們都有類似的方法和屬性。有些包含完全相同的方法和屬性,有些可能略有不同,有些可能會有很大差異。現在,我爲每個系統都有很多重複的代碼。例如,我有一個爲每個系統定義的名爲GetPropertyInformation()的方法。我試圖找出哪一種方法是減少重複的代碼或以下方法也許一個最好的辦法是不是要走的路:

接口

public Interface ISystem 
{ 
    public void GetPropertyInformation(); 
    //Other methods to implement 
} 

public class A : ISystem 
{ 
    public void GetPropertyInformation() 
    { 
     //Code here 
    } 
} 

摘要

在超基類
public abstract class System 
{ 
    public virtual void GetPropertyInformation() 
    { 
     //Standard Code here 
    } 
} 

public class B : System 
{ 
    public override void GetPropertyInformation() 
    { 
     //B specific code here 
    } 
} 

虛擬方法

public class System 
{ 
    public virtual void GetPropertyInformation() 
    { 
    //System Code 
    } 
} 

public class C : System 
{ 
    public override void GetPropertyInformation() 
    { 
     //C Code 
    } 
} 

一個問題,儘管它可能是愚蠢的,是讓我們假設我去與抽象的方法,我想重寫GetPropertyInformation,但我需要它傳遞一個額外的參數,這是可能的,或者我會在抽象類中創建另一個方法?例如,GetPropertyInformation(x)

回答

6

您的抽象和「超級基礎」方法並沒有太大的差異。你應該總是使基類抽象,並且你可以提供一個默認的實現(虛方法)或不提供(抽象方法)。決定性因素是你是否想要擁有基類的實例,我認爲不是。

所以它介於基類和接口之間。如果您的A,B C類之間存在強大的耦合,那麼您可以使用基類,也可能使用通用實現。

如果A,B,C類自然不屬於一個「家庭」,則使用一個接口。

System並不是這樣一個好名字。

而且重寫時不能更改參數列表。也許默認參數可以幫助,否則你只需要2次重載GetPropertyInformation()。

+0

我有一種感覺,抽象和超級基類是相似的。 A,B,C系統確實具有強大的耦合。有一個行業標準,但不必遵循,所以每個人都可以採用標準或改變他們的標準。在匆忙中,我選擇了系統:) – Xaisoft

+0

順便說一句好話。 – Xaisoft

3

一般情況下,如果您想共享實施並減少原本會重複的內容,請選擇對象繼承。否則接口會贏,因爲它們更加靈活,因爲不需要共同的基類。

至於重寫一個方法和修改參數列表是不可能的。想象一下,你將如何在基類或接口引用上調用該方法?

+0

它是「可能的」 - 你應該能夠聲明這樣的方法,它不再是原始方法的重寫。 – millimoose

+2

@Sii當然是不可能的。問題要求*重寫*方法並添加一個參數。這是不能做到的。 –

+0

我有一種感覺無法完成,一廂情願的想法。 – Xaisoft

3

我會像下面添加的東西一樣。您仍然可以從界面合同和共享實施中獲益。

public Interface ISystem 
{ 
    public void GetPropertyInformation(); 
    //Other methods to implement 
} 

public abstract class System : ISystem 
{ 
    public virtual void GetPropertyInformation() 
    { 
     //Standard Code here 
    } 
} 

public class B : System 
{ 
    public string ExtendedSystemProp {get;set;} 

    public override void GetPropertyInformation() 
    { 
     base.GetPropertyInformation(); 

     var prop = "some extra calculating"; 

     GetExtraPropertyInformation(prop); 
    } 

    public void GetExtraPropertyInformation(string prop) 
    { 
     ExtendedSystemProp = prop; 
    } 
} 

ISystem genericSystem = new B(); 
genericSystem.GetPropertyInformation(); 

(genericSystem as B).ExtendedSystemProp = "value"; 
+0

你能詳細說明爲什麼你會這樣做嗎? – Xaisoft

+0

這樣,即使只使用ISystem接口進行編程時,您仍然可以獲得所有屬性(當您擁有它們時應該這樣做)。但是,如果您在僅存在B的上下文中進行編碼:'B bSystem = new B();'您還公開了'B'特定方法以供明確使用。 – scottm

2

您無法在覆蓋中傳遞額外的參數。當你壓倒一切時,你會用確切的簽名覆蓋方法。我建議你傳入一個接口參數,如IPropertyInformation,每個實現可以更改。

決定使用基類還是接口來實現您的實現取決於您的使用。 A-I是否有足夠的共同點,他們應該真的都來自同一個基類?如果是這樣,那麼使用基類。是否真的只是共享GetPropertyInformation,否則系統在功能上完全不同?那麼你真的只是想讓他們分享一個界面。

2

其他人已經涵蓋了我的答案中最初的內容,但關於「添加參數」一點:不要忘記,最新的C#還允許您在方法中使用可選參數。

+0

但我必須在開始時聲明可選參數。我可能不知道我需要一個參數,直到1年後,所以在這種情況下,可選參數對我沒有好處。 – Xaisoft

2

除非你有一個令人信服的理由,否則,我會去接口。公共虛擬方法雖然做了很多,但是是not ideal