Oto działający kod dla 2.9.x. Poda ostrzeżenia o przestarzałości w wersji 2.10.x, ale zastąpi je ClassTag
zamiast Manifest
i runtimeClass
zamiast erasure
.
wyniki
//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)
Testowanie:
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
Kod jest nieco bardziej gadatliwy niż potrzeba tutaj, głównie dlatego wziąłem go z istniejącym kodzie kopalni, gdzie mogę używać ifInstanceOfBody gdzie indziej. Podpisanie pod asInstanceOfOpt
naprawiłoby to i nieco skróciło kod, ale większość jest dla primitiveToBoxedMap
i ufam, że nie mogłem znaleźć czegoś takiego dostępnego w standardowej bibliotece Scala.
Powyższy kod nie działa z powodu boksowania. '1.asInstanceOfOpt [Int]' zwraca 'None', podczas gdy' 1.asInstanceOfOpt [java.lang.Integer] 'zwraca' Some (1) 'with type' Option [Integer] '. Trzeba ręcznie odwzorować typy (opublikuję rozwiązanie). – Blaisorblade