ここでは2.9.x用の作業コードです。 2.10.xの非推奨警告が表示されますが、Manifest
の代わりにClassTag
を使用し、erasure
の代わりにruntimeClass
を使用すると、それらが修正されます。
//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
コード私は、私は他の場所でifInstanceOfBodyを再利用する私の既存のコードベースから、それを取った主な理由は、ここで必要とされるよりやや冗長です。 asInstanceOfOpt
にインライン展開するとコードが少し修正されますが、そのほとんどはprimitiveToBoxedMap
であり、Scala標準ライブラリで利用可能なものを見つけることができないと私を信じています。
上のコードはボクシングのために動作しません。 '' 1.asInstanceOfOpt [Int] 'は' None'を返し、 '1.asInstanceOfOpt [java.lang.Integer] 'は' Option [Integer] '型の' Some(1) 'を返します。手動でタイプをマッピングする必要があります(私は解決策を投稿します)。 – Blaisorblade