Scala covariance and contravariance

Java introduces generic in version 1.5. When we create a class B which is subclass of class A, then List<B> is not a subclass of type List<A>. Which is little weird but its like that.

Scala extends this to next level and give flexibility where a generic class(say List)  can be or can not be subclass of A. There are 3 possibility.
 1. covariance i.e generic class [B] is subclass of generic class[A]
 2. contravariance where generic class[A] is subclass of generic class[B], reverse inheritance
 2. no relationship, like Java. This is default behaviour.
Lets check this by example. Scala list is defined as covariance, so following code will work fine.
val list:List[A] = List[B]()

Lets define a class with default behaviors, then we will modify this class to check other 2. 

scala> class GenericClass[A] {
| def sayHello = println("Hello Vivek!");
| }
defined class GenericClass

scala> val x:GenericClass[A] = new GenericClass[B]()
:13: error: type mismatch;
found : GenericClass[B]
required: GenericClass[A]
Note: B You may wish to define A as +A instead. (SLS 4.5)
val x:GenericClass[A] = new GenericClass[B]()
^

Here it clearly shows that GenericClass[B] is not subtype of GenericClass[A] and in fact suggesting us to make GenericClass covariance of type A (i.e GenericClass[+A] ) to make it work.

Lets Define GenericClass as covariance of type A

scala> class GenericClass[+A] {
| def sayHello = println("Hello Vivek!");
| }
defined class GenericClass
scala> val x:GenericClass[A] = new GenericClass[B]()
x: GenericClass[A] = GenericClass@47b77e9b

 This works pretty well. Lets check what happens when we make GenericClass as contra variance of type A ie( GenericClass[-A])

scala> class GenericClass[-A] {
| def sayHello = println("Hello Vivek!");
| }
defined class GenericClass
scala> val x:GenericClass[A] = new GenericClass[B]()
:13: error: type mismatch;
found : GenericClass[B]
required: GenericClass[A]
val x:GenericClass[A] = new GenericClass[B]()
^
scala> val x:GenericClass[B] = new GenericClass[A]()
x: GenericClass[B] = GenericClass@1c8873e3

Here we see that GenericClass's inheritance relationship is reversed. Now GenericClass[A] is subtype of GenericClass[B]

There are lots of other feature which is new(with respect to Java) in Scala type system. I will try to explain bound in next blog.
 
 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s