如何在Scala中编写"asInstanceOfOption"

Mat*_*t R 26 scala

是否可以编写一个"asInstanceOfOption"方法来执行以下(伪造)代码的意图?

def asInstanceOfOption[T](o: Any): Option[T] =
   if (o.isInstanceOf[T]) Some(o.asInstanceOf[T]) else None 
Run Code Online (Sandbox Code Playgroud)

oxb*_*kes 29

编辑 以下是我原来的答案,但你现在可以完成这个

def asInstanceOfOption[T: ClassTag](o: Any): Option[T] = 
  Some(o) collect { case m: T => m}
Run Code Online (Sandbox Code Playgroud)

您可以使用清单以绕过事实类型T被擦除在编译时:

scala> import scala.reflect._
import scala.reflect._

scala> def asInstanceOfOption[B](x : Any)(implicit m: Manifest[B]) : Option[B] = {
   | if (Manifest.singleType(x) <:< m)
   |   Some(x.asInstanceOf[B])
   | else
   |   None
   | }
asInstanceOfOption: [B](x: Any)(implicit m: scala.reflect.Manifest[B])Option[B]
Run Code Online (Sandbox Code Playgroud)

然后可以使用:

scala> asInstanceOfOption[Int]("Hello")
res1: Option[Int] = None

scala> asInstanceOfOption[String]("World")
res2: Option[String] = Some(World)
Run Code Online (Sandbox Code Playgroud)

您甚至可以使用隐式转换来使其成为可用的方法Any.我想我更喜欢方法名称matchInstance:

implicit def any2optionable(x : Any) = new { //structural type
  def matchInstance[B](implicit m: Manifest[B]) : Option[B] = {
    if (Manifest.singleType(x) <:< m)
      Some(x.asInstanceOf[B])
    else
      None
  }   
}
Run Code Online (Sandbox Code Playgroud)

现在您可以编写如下代码:

"Hello".matchInstance[String] == Some("Hello") //true
"World".matchInstance[Int] == None             //true    
Run Code Online (Sandbox Code Playgroud)

编辑:2.9.x的更新代码,其中一个不能使用Any但仅限AnyRef:

implicit def any2optionable(x : AnyRef) = new { //structural type
  def matchInstance[B](implicit m: Manifest[B]) : Option[B] = {
    if (Manifest.singleType(x) <:< m)
      Some(x.asInstanceOf[B])
    else
      None
  }   
}
Run Code Online (Sandbox Code Playgroud)

  • 只有一个观察; "结构类型"使用反射来调用`matchInstance`方法.如果性能更为关键,则可以使用标准转换为非结构类型 (2认同)