Liskov的字符串替换和组成字符串、Liskov

2023-09-02 23:45:40 作者:逝去の注定无返

让说,我有一类这样的:

Let say I have a class like this:

public sealed class Foo
{
    public void Bar
    {
       // Do Bar Stuff
    }
}

和我想扩展它添加的东西超出了一个扩展方法可以做到....我唯一的选择是组成:

And I want to extend it to add something beyond what an extension method could do....My only option is composition:

public class SuperFoo
{
    private Foo _internalFoo;

    public SuperFoo()
    {
        _internalFoo = new Foo();        
    }

    public void Bar()
    {
        _internalFoo.Bar();
    }

    public void Baz()
    {
        // Do Baz Stuff
    }
}

虽然这个作品,它是一个大量的工作......不过,我仍然会碰到一个问题:

While this works, it is a lot of work...however I still run into a problem:

  public void AcceptsAFoo(Foo a)

我可以在富路过这里,但不是超级富,因为C#不知道是SuperFoo确实只限定在Liskov替换感......这意味着,我的作文,通过扩展类是非常有限的。

I can pass in a Foo here, but not a super Foo, because C# has no idea that SuperFoo truly does qualify in the Liskov Substitution sense...This means that my extended class via composition is of very limited use.

因此​​,要解决这个问题的唯一办法就是希望原来的API设计人员留下了接口周围铺设:

So, the only way to fix it is to hope that the original API designers left an interface laying around:

public interface IFoo
{
     public Bar();
}

public sealed class Foo : IFoo
{
     // etc
}

现在,我可以实现的IFoo上SuperFoo(这是自SuperFoo已经实现了富,是改变签名只是一个问题)。

Now, I can implement IFoo on SuperFoo (Which since SuperFoo already implements Foo, is just a matter of changing the signature).

public class SuperFoo : IFoo

而在完美的世界,消耗符的方法将消耗的IFoo的:

And in the perfect world, the methods that consume Foo would consume IFoo's:

public void AcceptsAFoo(IFoo a)

现在,C#理解SuperFoo与富之间的关系,由于共同的界面,一切都很好。

Now, C# understands the relationship between SuperFoo and Foo due to the common interface and all is well.

的大问题是,.NET海豹很多类,偶尔会是不错的延伸,他们通常不会实现一个共同的接口,以便采取富不会接受一个SuperFoo,你API方法不能添加的过载。

因此​​,对于所有的组成球迷在那里....你如何解决这一限制得到什么呢?

So, for all the composition fans out there....How do you get around this limitation?

我唯一能想到的是暴露出内部美孚公开,这样就可以通过它一次,但似乎乱了。

The only thing I can think of is to expose the internal Foo publicly, so that you can pass it on occasion, but that seems messy.

推荐答案

恐怕简单的答案是,你不能没有做什么是必需的,即通过组成的实例变量来代替。

I'm afraid the short answer is, you can't without doing what is required, i.e. pass the composed instance variable instead.

您可以允许隐式或显式转换到该类型(它的实现简单地传递组成的实例),但这会,IMO是pretty的恶。

You could allow an implicit or explicit cast to that type (whose implementation simply passed the composed instance) but this would, IMO be pretty evil.

sixlettervariable的回答是好的,我不会重复,但如果你表明你希望哪些类,你可以扩展我们也许能够告诉你他们为什么prevented吧。

sixlettervariable's answer is good and I won't rehash it but if you indicated which classes you wished you could extend we might be able to tell you why they prevented it.