2010-07-15 59 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(); 
}