user7938511
user7938511

Reputation: 167

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

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

Answers (3)

Alexey Romanov
Alexey Romanov

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

jwvh
jwvh

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

simpadjo
simpadjo

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

Related Questions