c# – Liskov分解和组成

前端之家收集整理的这篇文章主要介绍了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它,但如果你指出你希望你可以延伸的课程,我们可能可以告诉你为什么他们阻止它.

猜你在找的C#相关文章