scala variance and contravariance


scala covariance and contravariance 

trait Function1[-P, +R] { ... }

prameter is contravariance and result is covariance

/**
 * Created by Rosin on 2014/7/3.
 */
object Main20140703 extends App{

  val doAVary: Function1[MyGrandChild, GrandChildReturn] = { x: MyChild => new MyGrandChild }

  //doAVary(new MyGrandGrandGrandChild)
}

class Me{}

class MyChild extends Me{}

class MyGrandChild extends MyChild

class MyGrandGrandChild extends MyGrandChild

class MyGrandGrandGrandChild extends MyGrandGrandChild



class AReturn

class ChildReturn extends AReturn{}

class GrandChildReturn extends ChildReturn{}

class GrandGrandChildReturn extends GrandChildReturn{}

class GrandGrandGrandChildReturn extends GrandGrandChildReturn{}

mutable collections are invarian(neither covariance nor contravariance)

A type parameter is invariant when it’s neither covariant nor contravariant. All Scala mutable collection classes are invariant. 

An example can explain why mutable objects need to be invariant. By now, you should be comfortable using collection .immutable.List;

the mutable counterpart of List is collection.mutable.ListBuffer. Because ListBuffer is mutable, it’s declared as invariant as follows: 

final class ListBuffer[A]  ...{ ... }

Notice that when you declare an invariant type, you drop the - or + sign. Because it’s

declared as invariant, you can’t assign ListBuffer from one type to another. The

following code will throw a compilation error:

scala> val mxs: ListBuffer[String] = ListBuffer("pants")
mxs: scala.collection.mutable.ListBuffer[String] = ListBuffer(pants)
scala> val everything: ListBuffer[Any] = mxs
<console>:6: error: type mismatch;
 found   : scala.collection.mutable.ListBuffer[String]
 required: scala.collection.mutable.ListBuffer[Any]
       val everything: ListBuffer[Any] = mxs

Even though String is a subtype of scala.Any, Scala still doesn’t let you assign mxs

to everything. To understand why, assume ListBuffer is covariant and the following

code snippet works without any compilation problem:

scala> val mxs: ListBuffer[String] = ListBuffer("pants")
mxs: scala.collection.mutable.ListBuffer[String] = ListBuffer(pants)
scala> val everything: ListBuffer[Any] = mxs
scala> everything += 1
res4: everything.type = ListBuffer(1, pants)

Can you spot the problem? Because everything is of the type Any, you can store an integer value into a collection of strings. This is a disaster waiting to happen.

 It’s exactly what happens to Java arrays. To avoid these kinds of problems, it’s always a good idea to make mutable objects invariant. 

The next question is what happens in case of an immutable object for collections. It turns out that for immutable objects,

covariance isn’t a problem at all. If you replace ListBuffer with the immutable List, you can take an instance of List[String] and assign it to List[Any] without a problem.

because mxs is a mutable LisBuffer,even though mxs has been assigned to the everything which is of type ListBuffer[String] ,but actually,mxs's real type is [String]

what if a morphysm method invoke on everything invoke ..... actually invoke on String.

scala> val xs: List[String] = List("pants")
xs: List[String] = List(pants)
scala> val everything: List[Any] = xs
everything: List[Any] = List(pants)

The only reason this assignment is safe is because List is immutable. You can add 1 to xs List, and it will return a new List of type Any.

scala> 1 :: xs
res5: List[Any] = List(1, pants)

now you can not make a morphysm method invoke on res5.because it's actual type is really Any.

Again, this addition is safe because the cons(::) method always returns a new List, and its type is determined by the type of elements in the List. The only type that could store an integer value and reference value is scala.Any. 

This is an important property to remember about type variance when dealing with mutable/ immutable objects.


转载于:https://my.oschina.net/dingohaha60/blog/287111

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值