Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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"); }
    }
}
Licensed under: CC-BY-SA with attribution
scroll top