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

后端 未结 3 848
借酒劲吻你
借酒劲吻你 2021-02-06 03:41

There\'s a handy implementation of asInstanceOfOpt, a safe version of asInstanceOf, given in the answer to How to write "asInstanceOfOption"

3条回答
  •  孤独总比滥情好
    2021-02-06 04:10

    Here's working code for 2.9.x. It will give deprecation warnings for 2.10.x, but using ClassTag instead of Manifest and runtimeClass instead of erasure will fix them.

    //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)
    

    Testing results:

    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
    

    The code is slightly more verbose than needed here, mostly because I took it from an existing codebase of mine where I reuse ifInstanceOfBody elsewhere. Inlining into asInstanceOfOpt would fix that and shorten the code somewhat, but most of it is for primitiveToBoxedMap, and trust me that I could not find something like that available in the Scala standard library.

提交回复
热议问题