Is array of Dogs an array of Animals? Covariance, contravariance and invariance explained – part 2

This post is a continuation of Is array of Dogs an array of Animals? Covariance, contravariance and invariance explained – part 1.

Method overriding

Type variance is not just relevant to generics but also to ineritance of regular, not generic, classes.

When overriding a method in a class you usually make sure that it has the same argument types and return type. Note that it is not always necessary.

For example, it makes sense for the overriding method to return a subtype of the return type of the original method.

The caller of getAnimal will expect an instance of Animal. Returning something more derived (a Dog) will be perfectly type safe. Therefore, we can say that return type of overriden method is covariant.

read more

Is array of Dogs an array of Animals? Covariance, contravariance and invariance explained – part 1

Welcome to the first post on my blog. I would like to dedicate it to a topic that sounds quite intimidating but is in fact quite simple to understand. There are already good explanations of type variance to be found on other blogs or Stack Overflow but I would like to take a broader approach and look at how different programming languages deal with it.

The problem

So, what is this cryptic title about? Let me start with this classic example in Java.

Would you expect this piece of code to compile? The answer depends on what operations are available on MyList. Let’s assume that MyList is very similiar to ArrayList and it allows you to get and add.

Now, assuming that the questioned piece of code would compile, it would be perfectly valid to add a Cat to the list of Animals which is in fact a list of Dogs. This is not something we would want the compiler to allow.

In this case, MyList<Dog> is not (does not inherit from) MyList<Animal>. We call MyList invariant. This is the kind of behaviour that we get in Java.

read more