说我有一个这样的课:
public sealed class Foo { public void Bar { // Do Bar Stuff } }
我想扩展它以添加一些扩展方法可以做的事情….我唯一的选择是组合:
public class SuperFoo { private Foo _internalFoo; public SuperFoo() { _internalFoo = new Foo(); } public void Bar() { _internalFoo.Bar(); } public void Baz() { // Do Baz Stuff } }
虽然这是有效的,但它是很多工作…但是我仍遇到一个问题:
public void AcceptsAFoo(Foo a)
我可以在这里传递一个Foo,但不能超过Foo,因为C#不知道SuperFoo真的有资格在Liskov替代方面使用这个意思,这意味着我的扩展类通过组合是非常有限的使用.
所以,解决它的唯一方法是希望原来的API设计师留下一个接口:
public interface IFoo { public Bar(); } public sealed class Foo : IFoo { // etc }
现在,我可以在SuperFoo上实现IFoo(由于SuperFoo已经实现了Foo,只是改变了签名的一个问题).
public class SuperFoo : IFoo
在完美的世界中,消费Foo的方法将消耗IFoo的:
public void AcceptsAFoo(IFoo a)
现在,C#由于通用接口了解SuperFoo和Foo之间的关系,一切都很好.
最大的问题是.NET封装了许多有时候很好扩展的类,并且它们通常不会实现一个通用的接口,所以使用Foo的API方法不会接受SuperFoo,并且不能添加一个超负载.
所以,所有的组合粉丝在那里….你如何解决这个限制?
我唯一可以想到的是公开暴露内部的Foo,以便您可以偶尔传递它,但这似乎凌乱.
解决方法
恐怕简短的答案是,你不能没有做所需要的,也就是传递合并的实例变量.
您可以允许隐式或显式的转换(该实现只是通过编译的实例),但是这样做会使IMO变得非常恶劣.
sixlettervariable的答案是好的,我不会rehash它,但如果你指出你希望你可以延伸的课程,我们可能可以告诉你为什么他们阻止它.