程式扎記: [Scala 常見問題] covariant type T occurs in contravariant position

標籤

2016年7月21日 星期四

[Scala 常見問題] covariant type T occurs in contravariant position

Source From Here 
Question 
I know this question has been asked before, but either the answers don't apply to this case, or I don't understand them. Basically, why doesn't the following (simple example that recreates my problem) work ? 
  1. class Test[+T] {  
  2.     var list: List[T] = _  
  3. }  
The problem I am having is that I have an object, where I want to pass in an instance of Test[Nothing] (the empty Test), and this doesn't work unless I make Test co-variant in T

How-To 
Making Test covariant in T means that Test[A] is a subtype of Test[Any] for any A. So lets create a Test
  1. val test_string = new Test[String]  
Now we have a Test[String] and the contained list is type List[String]. Since Test[String] is a subtype of Test[Any], the following should be allowed: 
  1. val test_any : Test[Any] = test_string  
And now, we have a Test[Any], and therefore test_any.list is type List[Any], which means the following should be valid: 
  1. test_any.list = List[Any]()  
Which means we just assigned a List[Any] to test_strings list member, which shouldn't be allowed, since that is supposed to be a List[String], not a List[Any]. It also means you could prepend anything at all to the list, since it is typeList[Any]. A proper way to carry out your requirement is to: 
scala> class Test[+T](val value:List[T]) { def list[A >: T]():List[A]=value }
defined class Test

scala> val test = new Test(List(1,2,3))
test: Test[Int] = Test@2e3bb3fd

scala> test.list
res6: List[Int] = List(1, 2, 3)

scala> val a:Test[Any] = test
a: Test[Any] = Test@2e3bb3fd

scala> a.list
res7: List[Any] = List(1, 2, 3)

scala> 1 :: a.list
res8: List[Any] = List(1, 1, 2, 3)


Supplement 
Scala Gossic : 繼續深入 - 型態參數化 (Covariance)

沒有留言:

張貼留言

網誌存檔