I have read a few question on SO and elsewhere and still do not understand well where this "widening" of a parameter type can be helpful, i.e. compliying to Liskov substitution principle. The following code I took from an answer here on SO, explaining contravariance:
//Contravariance of parameter types: OK
class Food
class FastFood extends Food
class Person { eat(FastFood food) }
class FatPerson extends Person { eat(Food food) }
So I understand that the overridden method accepts more generic paramater than the method in its ancestor. But in practice, how does this help? I mean, if the original method works with certain properties of the derived type, none of this will be available in the derivative using the supertype of the parameter. Therefore, I might have issues with fulfiffing the contract postcontionds, if those relate to the subtype somehow.
Like:
class Animal {}
class Cat { void Meow() void CatSpecificThing()}
...
class A
{
List<Cat> ListOfCats;
void X(Cat c)
{
c.Meow()
c.CatSpecificThings()
ListOfCats.Add(c)
}
}
class B : A
{
void X(Animal a)
{
//how is this now useful? I cannot do anything that needed Cat
}
}
Let's say the postcondtion of X method is to update the ListOfCats. But in the overriden method in the derived class, I would not be able to do it if there was just the supertype..?
I would be extremely happy for a simple example that demonstrates how this is useful.