Pergunta

How is this possible:

import scala.util.{Try, Success}
import reflect._

case class Foo[A](x: A) extends Dynamic {

  def get[T: ClassTag]: Option[T] = Try(x.asInstanceOf[T]) match {
    case Success(r) => Some(r) 
    case _ => None
  }
}

object Foo extends App {
  val test = Foo("hi")
  val wtf: Option[Int] = test.get[Int]
  assert(wtf.isInstanceOf[Option[String]])
  assert(wtf == Some("hi"))     // how????
  // val wtf2: Option[String] = wtf  // does not compile even if above assert passes!!
}

Inspired by this question: Scala check type of generics

Foi útil?

Solução

  1. Due to type erasure, wtf.isInstanceOf[Option[String]] can only check that wtf is an instance of Option, but not the type parameter. Similarly, asInstanceOf[T] is actually a cast to Object at the runtime, and so it succeeds. You need to do

    classTag[T].runtimeClass.cast(x)
    

    instead.

  2. The compiler can't use the information from asserts passing (you can imagine a compiler which could, but Scala simply isn't designed like that). It only knows that the type of wtf is Option[Int], so of course you can't initialize an Option[String] with it. If you want to get something like that, you need

    wtf match {
      case wtf2: Option[String] => ...
    }
    

    Of course, this doesn't work correctly due to point 1.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top