2010-07-15 92 views
9

我需要爲現有接口上的函數創建重載,而不會影響當前實現或使用該接口(理想情況下)的任何組件。向接口添加新功能

我想我有幾個選擇:

簡體 原始界面:

public interface IServerComponent 
{ 
    bool Add(int a, int b); 
} 

我可以添加新的重載函數的接口,並迫使每一個實現接口的類實施新功能。

public interface IServerComponent 
{ 
    bool Add(int a, int b); 
    bool Add(int a, int b, int c); 
} 

或者我可以創建一個實現原始接口的新接口。然後,其他類,利用原有的不需要改變任何新的類可以實現新的界面...

public interface IServerComponent2 : IServerComponent 
{ 
    bool Add(int a, int b, int c); 
} 

什麼是最好的做法是這樣的情況嗎?還有其他選擇嗎?

感謝

回答

11

如果新方法能夠在舊的方法來表示,您可以使用擴展方法:

// Original interface 
public interface IServerComponent 
{ 
    bool Add(int a, int b, int c); 
} 

// New overload 
public static class MyServerMethods 
{ 
    public static bool Add(this IServerComponent component, int a, int b) 
    { 
    return component.Add(a, b, 0); 
    } 
} 

如果方法不一樣,來表示(即它們真的需要由組件本身來實現),那麼我建議定義一個新的接口。這種方法具有最大的後向兼容性。

+0

+1提的擴展方法 – ram 2010-07-15 13:51:08

+1

擴展方法將工作,但也會有分散到其他班級的凝聚力降低實現類的功能的效果。我認爲這是最好的臨時解決方案。在無法擴展類的情況下,因爲您無法訪問源,所以擴展方法是有意義的。我可能以這種方式對現有代碼庫進行微小更新,但我肯定會將其放在下一個主要版本的重構列表中。 – tvanfosson 2010-07-15 13:58:51

+2

這完全取決於設計。如果您添加*新功能*,那麼我會同意;它屬於一個接口。如果你添加*超載*(例如,幾乎相同的功能,總是表達其他功能),然後我不同意。在這種情況下,擴展方法允許*正交性,減少代碼重複。 [Joe Duffy](http://www.bluebytesoftware.com/blog/2010/02/10/ExtensionMethodsAsDefaultInterfaceMethodImplementations.aspx)在這個主題上有一篇很好的博客文章。 – 2010-07-15 14:10:30

4

如果您的IServerComponent接口尚未發佈,或者是僅由您自己的類實現的內部接口,並且新接口成員對於實現接口的所有現有類都有意義,請更改現有接口。

否則,創建一個擴展IServerComponent的IServerComponent2接口。 IIRC這是框架設計指南推薦的內容。可以在類似X509Certificate2類的.NET Framework中找到此示例。

然而,如果新的成員可以在原有會員的角度來實現的,你也可以使用extension methods

public interface IServerComponent 
{ 
    bool Add(int a, int b); 
} 

public static class ServerComponentExtensions 
{ 
    public static bool Add(this IServerComponent isc, int a, int b, int c) 
    { 
     return isc.Add(a, b) && isc.Add(b, c) && isc.Add(c, a); 
    } 
} 
0

這取決於上下文 - 如果有執行原接口很多類,或者如果它發佈了,那麼唯一可行的方法就是引入新的。另一方面,從長遠來看,只有一個接口更清潔,所以如果你負擔得起,我會說重構現有接口。

0

如果您不需要或想要更改已經實現舊界面的類(現在或將來),則應該創建第二個界面。但是,它更像是一種黑客攻擊,並且可能會給你更直觀的代碼。

另外,推遲重構在我的經驗中從來不是一個好主意。所以如果你懷疑你以後需要實現這個接口,那麼你可能只需要改變現有的接口,並省去一些頭痛的問題。它絕對是更乾淨的方式來做到這一點。

0

我覺得保持一個單一的界面是容易,但與2接口的第二種方法比較好,因爲不是每個類需要實現bool Add(int a, int b, int c);

1

我明白你的例子是人爲的,但我想給你一個人爲的答案是與你所表達的不同,所以你可以用不同的方式思考它。而不是讓你的接口方法在具體的東西上運行,它可能對它有意義,而不是抽象的東西。

例如

public interface IAddableThings 
{ 
    int a; 
    int b; 
} 

public interface IOtherAddableThings : IAddableThings 
{ 
    int a; 
    int b; 
} 

public interface IServerComponent 
{ 
    bool Add(IAddableThings things); 
} 

如果這確實是一個加那麼我認爲這使得很多更有意義,但如果是真的更像計算(),你會再想要移動的部分或全部該方法向下操作IAddableThings對象。

public interface IAddableThings 
{ 
    int a; 
    int b; 
    bool CalculateMe(); 
}