斯卡拉:我如何让这个玩具协变的例子起作用?

时间:2017-07-01 18:35:47

标签: scala covariance

简单协方差示例:为什么asInstance有效?

 class Fruit(name: String) { def get_name = name}
 class Apple(name: String)  extends Fruit(name)
 class Orange(name: String) extends Fruit(name)
 class BigOrange(name:String) extends Orange(name)

  // Contrived but simple covariant box with some utility functions
  class Box[+T <: Fruit] {
   def foo[ U >: T] (item: U): String = item.asInstanceOf[T].get_name 
  }

  val f = new Fruit("fruit")
  val a = new Apple("apple")
  val o = new Orange("orange")

  // Error. Makes sense apples cannot be casted to oranges
  println( a.asInstanceOf[Orange]) 


  val bo1 = new Box[Orange]
  println(bo1.foo(a)) // Returns Apple ! How was an apple seemingly casted to an orange?

那为什么最后一行有效呢?是不是要求将传递的苹果变成橙色的逻辑?

第二个问题:为什么这段代码会给我get_name not not error?

class Box[+T <: Fruit] (item: T) {
  val contents = item
  def foo[ U >: T] (item: U): String = item.get_name
}

在[+ T&lt ;: Fruit]和U&gt;:T之间,是不是很明显该项应该有一个get_name?为什么错误?

3 个答案:

答案 0 :(得分:1)

asInstanceOf[T]实际上什么都不做,因为T的{​​{1}}类型已被删除。您还应该收到编译器的警告。

答案 1 :(得分:1)

这里的问题......

class Box[+T <: Fruit] (item: T) {
  val contents = item
  def foo[U >: T] (item: U): String = item.get_name
}

...是你用另一个item遮蔽了一个item: T。第1个get_name 有一个item: U成员,编译器可以识别,但第二个Fruit没有。它可以是get_name的父类或超类,这意味着无法保证'成员。

答案 2 :(得分:1)

  

在[+ T&lt ;: Fruit]和U&gt;:T之间,是不是很明显该项应该有一个get_name?

当然不是。例如,U = Any满足约束条件且没有get_name成员。