Liskov Substition and Composition

Posted by FlySwat on Stack Overflow See other posts from Stack Overflow or by FlySwat
Published on 2009-02-16T18:42:15Z Indexed on 2010/05/21 23:20 UTC
Read the original article Hit count: 268

Filed under:
|
|
|

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)

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.

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
}

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

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

public void AcceptsAFoo(IFoo a)

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

The big problem is that .NET seals lots of classes that would occasionally be nice to extend, and they don't usually implement a common interface, so API methods that take a Foo would not accept a SuperFoo and you can't add an overload.

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.

© Stack Overflow or respective owner

Related posts about lsp

Related posts about .NET