Reputation: 167
Simple Covariance Example: why does asInstance work?
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?
So why does the last line work ? Isn't the logic asking the passed apple to be casted to an orange?
A second question: Why does this code give me get_name not recognized error ?
class Box[+T <: Fruit] (item: T) {
val contents = item
def foo[ U >: T] (item: U): String = item.get_name
}
Between the [+T <: Fruit] and U >: T, is'nt it obvious that item should have a get_name? why the error?
Upvotes: 0
Views: 58
Reputation: 170745
Between the [+T <: Fruit] and U >: T, is'nt it obvious that item should have a get_name?
Of course it isn't. For example, U = Any
satisfies the constraint and doesn't have get_name
member.
Upvotes: 1
Reputation: 51271
The problem here ...
class Box[+T <: Fruit] (item: T) {
val contents = item
def foo[U >: T] (item: U): String = item.get_name
}
... is that you're shadowing one item
with another. The 1st, item: T
, does have a get_name
member that the compiler can recognize, but the 2nd, item: U
, doesn't. It could be a parent or superclass of Fruit
which means there is no guarantee of a get_name
member.
Upvotes: 1
Reputation: 4017
asInstanceOf[T]
actually does nothing because type T
of Box
is erased. You also should get a warning from the compiler.
Upvotes: 1