1

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?

12
  • 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). Commented Jan 29, 2018 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#. Commented Jan 29, 2018 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
    Commented Jan 29, 2018 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. Commented Jan 29, 2018 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
    Commented Jan 29, 2018 at 20:04

2 Answers 2

4

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.

1
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 and acknowledge you have read our privacy policy.

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