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



简单协方差示例:为什么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 <:水果] 和 U>:T 之间,项目应该有get_name不是很明显吗? 为什么会出现错误?

在 [+T <:水果] 和 U>: T 之间,项目应该有get_name不是很明显吗?

当然不是。例如,U = Any满足约束并且没有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成员。

相关内容

  • 没有找到相关文章

最新更新