0

Trying to practice LSP, the following is not really clear to me:

Liskov requirements (some)
-There must be contravariance of the method arguments in the subtype.
– There must be covariance of the return types in the subtype.

Also the method in a subclass could be declared with a parameter type that is more generic than in the base class, is that right? But as far as I know, that does not work, as I tried in C#:

class A
{
    public virtual void Test(Cat a)
    { }

}

class B : A
{
    public override void Test(Animal a)  //shouldn't this work to be Liskov compliant?
    {

    }
}

class Animal
{ }

class Cat : Animal
{ }

As, to my knowledge, CLR does not support covariance except for delegates and generics, how can we implement truly LSP compliant code if this cannot be met?

  • 1
    Are you referring to this article? If so, then note that the article is talking specifically about C# generics (about what's required for generics to be LSP compliant). – Filip Milovanović Jan 29 '18 at 15:45
  • @FilipMilovanović No, I have read materials relating to LSP, not language specific. All of the mention that these contra and covariance rules must apply in orded to be LSP compliant. But I cannot see how to do that in C#. – Ezoela Vacca Jan 29 '18 at 15:50
  • @EzoelaVacca, as the article explains, C# classes are invariant, unless generics are used. And generic variance can only be defined via interfaces. So if you want to be a LSP purist, you cannot use inheritance in C# as it doesn't support some of the requirements of LSP compliance. – David Arno Jan 29 '18 at 15:53
  • 1
    I am wondering, whether requesting exactly the same type (as we do in C#) would be considered LSP compliant. We are certainly not narrowing the type, just ensuring it is the same. – Ezoela Vacca Jan 29 '18 at 15:57
  • 1
    @EzoelaVacca I'm a little confused. Your example shows the subclass method declared as taking Animal but your comment seems to suggest something else. Are you saying you want to pass an object declared to be of type Animal to a method that is declared to take Dog? If so, that doesn't work. – JimmyJames Jan 29 '18 at 20:04
3

There is a widespread misunderstanding of subtyping rules. Indeed, in C# you can write a code that is fully LSP compliant, because:

Subtyping rule for function types: the argument types in the signature must be at least as general as the actual arguments, and the return type must be at least as specific as the actual return type.

So your code will be type safe with respect to variance as your types will be the same, satisfying the condition of function subtyping. In addition, a type A is also a subtype of itself, the relation is reflexive.

Liskov extends the subtyping rules by additional behavioral rules.

0

In this case, C# is more conservative than the hypothetical, with respect to the declared type.

Because all overrides of Test must accept Cats, they can't break the LSP this way.

You can however break it very easily with behaviour

class Tabby : Cat {}

class C : A
{
    public override void Test(Cat a)
    {
        if (!a is Tabby) { throw new Exception("Breaking Old Code"); }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.