加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – Liskov分解和组成

发布时间:2020-12-15 06:51:06 所属栏目:百科 来源:网络整理
导读:说我有一个这样的课: public sealed class Foo{ public void Bar { // Do Bar Stuff }} 我想扩展它以添加一些扩展方法可以做的事情….我唯一的选择是组合: public class SuperFoo{ private Foo _internalFoo; public SuperFoo() { _internalFoo = new Foo(
说我有一个这样的课:
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它,但如果你指出你希望你可以延伸的课程,我们可能可以告诉你为什么他们阻止它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读