Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

>most of the OOP programmers I know do not understand covariance and contravariance (whereas just about every functional programmer I know has mastered them)

I very much doubt this and I suspect it is more of a problem of how you framed it. I'm sure you would see more success if you framed it seeing if the following would compile.

    List list = new ArrayList<String>;
and for contravariance ,which is something that is not very common in practice

    Consumer printHashCode = o -> System.out.println(o.hashCode());
    Consumer<String> printStringHashCode = printHashCode;


Where is the variance in your example?


If you covariance, it's the first example because String is a subtype of Object. List is the same thing as List<Object>.

The first example is missing some parenthesis, but it should convoy my point.


Assuming we are talking about java, List is not the same as List<Object>.

List<Object> list = new ArrayList<String>(); will fail to compile.

Generic types in Java have no variance by default. The only type that can be assigned to List<String> is exactly List<String>.

Your example would want to be List<? extends Object> foo = new List<String>();

There is a reason for this. Consider:

  List<String> foo;
  List<Object> bar = foo;
  bar.add(new Integer(0));
If the above works, you would be adding an Integer to a collection of Strings, which is not sound.

In general, you typically want to be covarient in type parameters that are used for arguements, and contravariant in type parameters that are used for return values. In the general case, this is unworkable (since types parameters are often used for both), so the only reasonable behaviour is to be invariant.

Raw arrays in Java are actually covariant - which is not reasonable - and quickly result in a runtime type exception when you get to the "bar[0] = new Integer(0)" portion of the above example.

Scala allows you to explicitly mark type parameters as covariant or contravariant, as bellow:

    class Foo[+T] //Foo is covariant in T
    class Foo[-T] //Foo is contravarient in T
    class Foo[T]  //Foo is invarient in T
However, no equivelent mechanism exists in Java.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: