Hacker News new | ask | show | jobs
by clhodapp 2508 days ago
I'm not really sure what you mean. Variance just changes what is and is not a subtype/supertype. If List is covariant then List<T> is a subtype of List<U> if T is a subtype of U. So then, by induction, List<List<T>> is a subtype of List<List<U>> if T is a subtype of U. I'm not sure what's hilariously hard to follow here...
1 comments

Good point, it's a bad example because we assume we're just combining covariance which is intuitive.

Nevertheless, I have a point because:

1. Things get harder with contravariance. 2. Things get harder when you mix covariance and contravariance.

The prototypical covariance class is Producer<T> (with method produce() returning T) while for contravariance that's Consumer<T> (with method consume taking a T as parameter).

Assume each class has a superclass (Consumer0<T> and Producer0<T>) and a subclass (Consumer2<T> and Producer2<T>). Assume V extends U extends T.

Can you list the subclasses and superclasses of Consumer<Producer<U>>?

Personally, I have to think carefully about this for a minute or so, and I've been there before a couple times.

This is not an especially complex scenario either. I've seen things get worse in practice.

Ah, I can figure it out pretty easily for that example too but probably only because I am pretty familiar with variance and you chose really generous names. I personally find the reasoning about variance becomes a lot easier if you stop thinking about the definitions and start thinking about what you should be able to do. A producer of a subtype is technically also producing the supertype. A consumer of a supertype can totally consume the subtype.