2017-01-16 72 views
2

當在多個類中繼承相同的接口時,它是否沒有更新所有具有接口實現的類的問題?例如,如果我有一個由4個類實現的接口,並且將來可能會更多,並且如果我向僅由4個類中的一個類實現的接口添加任何方法,那麼,去這個接口是不是一件乏味的任務並用一個未實現的異常或其他東西來實現其餘的類。我知道你可能會質疑爲什麼我不能將該方法添加到類本身,原因是我在這裏使用了一個工廠,並且我用這些類的對象之一返回了接口的引用。關於我如何能夠採取這種方法的任何想法?對這種情況有沒有其他方法?問題繼承多個類中的相同接口

添加示例代碼對於上述方案

public interface ITest 
{ 
    string TestMethod1(string st, int ab); 
    int TestMethod2(string st); 
    void TestMethod4(int ab); 
    float ITest.TestMethod3(string st); 
} 
public class Class1 : ITest 
{ 
    public string TestMethod1(string st, int ab) 
    { 
     return string.Empty; 
    } 
    public void TestMethod4(int ab) 
    { 
     throw new NotImplementedException(); 
    } 

    public int TestMethod2(string st) 
    { 
     throw new NotImplementedException(); 
    } 

    public float TestMethod3(string st) 
    { 
     throw new NotImplementedException(); 
    } 
} 
public class Class2 : ITest 
{ 

    float ITest.TestMethod3(string st) 
    { 
     return float.Parse("12.4"); 
    } 

    void ITest.TestMethod4(int ab) 
    { 
     throw new NotImplementedException(); 
    } 
    public string TestMethod1(string st, int ab) 
    { 
     throw new NotImplementedException(); 
    } 

    public int TestMethod2(string st) 
    { 
     throw new NotImplementedException(); 
    } 
} 
public class Main 
{ 
    ITest test = null; 

    public ITest CreateFactory(TestType testType) 
    { 
     switch(testType) 
     { 
      case TestType.Class1: 
       test = new Class1(); 
       break; 
      case TestType.Class2: 
       test = new Class2(); 
       break; 
     } 
     return test; 
    } 
} 

enum TestType 
{ 
    Class1, 
    Class2 
} 
+0

這聽起來像你需要另一個界面,而不是修改第一個界面。添加一個會引發異常但除了一個實現的成員的想法聽起來是錯誤的。 –

+0

這樣的意思,我爲每個類添加一個接口呢?因爲未來其他班級也可能會發生變化。 – Blossom

+0

接口的要點正是所有實現它的類共享相同的成員。因此,如果你想添加一些成員到界面,你必須爲所有類都這樣做。但正如Charles已經提到的,你也可以定義一個接口 - 例如'IExtendedInterface' - 只有新類實現並且來自已經存在的接口並添加一些新成員。 – HimBromBeere

回答

4

例如,如果我具有由4類實現和在未來可能會更如果我添加任何方法將接口的接口只用4個類中的一個來實現,那麼用一個沒有實現的異常或其他東西去實現所有其他的類是不是一件繁瑣的工作。

接口是合同。如果您希望某些班級無法遵守合同,那麼他們不應該聲明他們這樣做。實施界面以簡單地拋出NotSupportedExceptionNotImplementedException應該是最後的手段;通常有更好更清潔的解決方案。

你的情況的解決方案是簡單地宣佈一個新的接口:

public interface IFrobbable //legacy version 
{ 
    void Frob() 
} 

public interface IFrobbableOnSteroids: IFrobbable //the new and improved frobbable wonder 
{ 
    void MegaFrob(); 
} 

經過改進的新的實現應該實現IFrobbableOnSteroids。注意這個新的接口自己實現IFrobbable;這意味着實現IFrobbableOnSteroids的任何對象都可以在「傳統」代碼(僅知道Frob)和更新代碼(知道MegaFrob)中使用。這具有很好的屬性,您不會破壞現有的客戶端代碼。

當然,你也可以簡單地使新的更新類實現兩個接口,但我個人更喜歡使一個接口包括其他。

「遺產」的班級,如果沒有足夠的幸運來加以改進,仍然會是簡單的凡人IFrobbable s,但這應該是。如果你不是FrobbableInSteroids,不要假裝是一個;正如我的國家(自由翻譯)所說的那樣,「容易抓住騙子而不是跛腳」。

UPDATE:

關於你對一個工廠方法的問題,以及考慮到你的類似乎是公開的,有一個enum沒有真正的理由。只需使用泛型和類型本身:

public static T CreateFrobbable<T>() 
    where T: IFrobbable, new() 
{ 
    return new T(); 
} 

public static T CreateFrobabbleOnSteroids<T>() 
    where T: IFrobbableOnSteroids, new() 
    { 
     return new T(); 
    } 

現在,如果我們有一個類SomeFrobbable: IFrobbable,您將創建一個簡單的調用CreateFrobbable<SomeFrobbable>()。並且SomeFrobbableOnSteroids: IFrobbableOnSteroids可以創建爲IFrobbableCreateFrobbable<SomeFrobbableOnSteroids>()或者作爲完整的IFrobbableOnSteroidsCreateFrobbableOnSteroids<SomeFrobbableOnSteroids>()創建。你不能做什麼,這是一件好事,是CreateFrobbableOnSteroids<SomeFrobbable>() //Compile time error

+0

+1這兩個答案,但是,我有點這樣做的困難,添加一個新的接口是好的,但正如我已經提到,我這樣做是爲了支持工廠模式,在那裏我實例化其中一個類,並返回接口的引用,現在添加一個新的實例意味着返回的引用不會有新成員在其中是正確的? – Blossom

+0

@Blossom那麼你的工廠應該知道如何提供這兩種類型:如果你要求'IFrobbable',那麼你應該返回一個'IFrobbable',而不管它是否是一個'IFrobbable'或者'IFrobbableOnSteroids'。另一方面,如果你要求一個'IFrobbableOnSteroids'然後通過一切手段返回一個。那些只能是'IFrobbable'的只能是那個。其他人可以是兩者,它由消費者決定他想要的物品的味道。 – InBetween

+0

是的,那正是我關心的問題,我已經將示例代碼添加到了我的問題中,您是否能夠幫助我如何在此情況下添加另一個接口的情況下如何修改工廠?我一直在努力尋找這種方法的解決方案。 – Blossom

2

對現有API進行更改已經很乏味,需要對API的現有客戶端進行很多更改。然而加入新成員是位容易,因爲你可以簡單地引入一個新的界面,增加了新的功能:

interface ITheInterface 
{ 
    void DoSomething(); 
} 

現在創建一個新的接口從現有的一個派生:

interface ITheInterface2: ITheInterface 
{ 
    void DoSomething2(); 
} 

常見的 - 但不一定是最好的 - 只是在接口名稱後面使用一個數字來表示它的版本 - 這裏是2,並標記舊的Obsolete表示有更新的版本。恕我直言,它會更好地添加一些名稱,指示新界面實際上做了什麼,這是新功能。

現在你所有的現有類仍然可以實現ITheInterface,而新的類實現新的接口。所以你不需要改變現有的代碼,但如果你實現了新的接口,可以消耗新的成員。