Scala:如何让这个玩具协变示例工作?

Scala: How do I get this toy covariant example to work?

简单协方差示例:为什么 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 无法识别的错误?

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

在 [+T <: Fruit] 和 U >: T 之间,不是很明显该项目应该有一个 get_name 吗?为什么会出错?

asInstanceOf[T] 实际上什么都不做,因为 Box 的类型 T 被删除了。您还应该从编译器那里得到警告。

这里的问题...

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

... 是您将一个 item 与另一个重叠。第一个 item: T 确实 有编译器可以识别的 get_name 成员,但第二个 item: U 没有。它可能是 Fruit 的父类或超类,这意味着不能保证 get_name 成员。

Between the [+T <: Fruit] and U >: T, is'nt it obvious that item should have a get_name?

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