Aquí está el código de trabajo para 2.9.x. Proporcionará advertencias de depreciación para 2.10.x, pero usando ClassTag
en lugar de Manifest
y en lugar de erasure
, los reparará.
resultados de las pruebas
//Precondition: classS must have been produced through primitiveToBoxed, because v will be boxed.
def ifInstanceOfBody[T, S](v: T, classS: Class[_]): Option[S] = {
if (v == null || !classS.isInstance(v))
None
else
Some(v.asInstanceOf[S])
}
object ClassUtil {
import java.{lang => jl}
private val primitiveToBoxedMap = Map[Class[_], Class[_]](
classOf[Byte] -> classOf[jl.Byte],
classOf[Short] -> classOf[jl.Short],
classOf[Char] -> classOf[jl.Character],
classOf[Int] -> classOf[jl.Integer],
classOf[Long] -> classOf[jl.Long],
classOf[Float] -> classOf[jl.Float],
classOf[Double] -> classOf[jl.Double],
classOf[Boolean] -> classOf[jl.Boolean],
classOf[Unit] -> classOf[jl.Void]
)
def primitiveToBoxed(classS: Class[_]) =
primitiveToBoxedMap.getOrElse(classS, classS)
}
class IfInstanceOfAble[T](v: T) {
def asInstanceOfOpt[S](implicit cS: Manifest[S]): Option[S] =
ifInstanceOfBody[T, S](v, ClassUtil.primitiveToBoxed(cS.erasure))
}
implicit def pimpInstanceOf[T](t: T) = new IfInstanceOfAble(t)
:
scala> 1.asInstanceOfOpt[Int]
res9: Option[Int] = Some(1)
scala> "".asInstanceOfOpt[String]
res10: Option[String] = Some()
scala> "foo".asInstanceOfOpt[String]
res11: Option[String] = Some(foo)
scala> 1.asInstanceOfOpt[String]
res12: Option[String] = None
scala> "".asInstanceOfOpt[Int]
res13: Option[Int] = None
El código es un poco más detallado de lo necesario aquí, sobre todo porque la tomé de una base de código existente de la mina donde reutilizar ifInstanceOfBody en otro lugar. Incluir en asInstanceOfOpt
lo arreglaría y acortaría un poco el código, pero la mayoría es para primitiveToBoxedMap
, y créame que no pude encontrar algo así en la biblioteca estándar de Scala.
El código anterior no funciona debido al boxeo. '1.asInstanceOfOpt [Int]' devuelve 'None', mientras que' 1.asInstanceOfOpt [java.lang.Integer] 'devuelve' Some (1) 'con el tipo' Option [Integer] '. Uno necesita mapear los tipos manualmente (voy a publicar una solución). – Blaisorblade