c# – Liskov分解和组成
说我有一个这样的课:
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它,但如果你指出你希望你可以延伸的课程,我们可能可以告诉你为什么他们阻止它. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 页面渲染传参的方式 - Node实战
- 本地SQLite DB的Android Content Provider:为什么?
- Cocos2dx:使用Cocos Studio创建一个简单的工程
- React+ajax+java实现上传图片并预览功能
- 适用于iPhone 5的图像命名约定
- ruby-on-rails – 安装Rails时出现“extconf.rb failed”消
- c – 对`std :: istreambuf_iterator`的使用感到困惑
- 常用正则表达式
- RSpec,Rails 4,Postgres,UUID主键:使用Rake RSpec,id为nul
- 原生ajax POST,解决Undefined index