Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write asInstanceOfOpt[T] where T <: Any

Tags:

scala

There's a handy implementation of asInstanceOfOpt, a safe version of asInstanceOf, given in the answer to How to write "asInstanceOfOption" in Scala. It appears that, Scala 2.9.1, this solution now only works with AnyRef:

class WithAsInstanceOfOpt(obj: AnyRef) {
  def asInstanceOfOpt[B](implicit m: Manifest[B]): Option[B] =
    if (Manifest.singleType(obj) <:< m)
      Some(obj.asInstanceOf[B])
    else
      None
}

Can this be rewritten to support Any?

like image 816
Matt R Avatar asked Oct 24 '11 10:10

Matt R


2 Answers

If you look in the Scala API the function singleType takes a parameter of type AnyRef. I don't really know the background for this decision, but it seems you need to work around it. Instead of using the method singleType I'd suggest using the classType method which basically can make a manifest for any class. It'll take a bit more code, but it could look something like this:

class WithAsInstanceOfOpt(obj : Any) {
  def asInstanceOfOpt[B : Manifest] : Option[B] =   // [B : Manifest] is shorthand for [B](implicit m : Manifest[B])
    if (Manifest.classType(manifest, obj.getClass) <:< manifest)
      Some(obj.asInstanceOf[B])
    else None
}
like image 142
Jens Egholm Avatar answered Oct 22 '22 09:10

Jens Egholm


You could use shapeless's Typeable from Miles Sabin:

Type casting using type parameter

It handles primitives and boxing:

scala> import shapeless._; import syntax.typeable._
import shapeless._
import syntax.typeable._

scala> 1.cast[Int]
res1: Option[Int] = Some(1)

scala> 1.cast[String]
res2: Option[String] = None

scala> "hello".cast[String]
res4: Option[String] = Some(hello)

scala> "foo".cast[Int]
res5: Option[Int] = None

You can see the source here to see how it's written:

https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/typeable.scala

like image 21
tksfz Avatar answered Oct 22 '22 09:10

tksfz