如何写“ asInstanceOfOption”在斯卡拉
-
05-07-2019 - |
题
是否可以编写“asInstanceOfOption”;可以执行以下(伪造)代码的方法吗?
def asInstanceOfOption[T](o: Any): Option[T] =
if (o.isInstanceOf[T]) Some(o.asInstanceOf[T]) else None
解决方案
编辑 以下是我的原始答案,但您现在可以使用
完成此操作def asInstanceOfOption[T: ClassTag](o: Any): Option[T] =
Some(o) collect { case m: T => m}
您可以使用清单在编译时解决类型 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]
然后可以使用:
scala> asInstanceOfOption[Int]("Hello")
res1: Option[Int] = None
scala> asInstanceOfOption[String]("World")
res2: Option[String] = Some(World)
您甚至可以使用隐式转换来使其成为 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
}
}
现在您可以编写如下代码:
"Hello".matchInstance[String] == Some("Hello") //true
"World".matchInstance[Int] == None //true
编辑: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
}
}
其他提示
这是关于oxbow_lake更新答案的详细说明,进一步更新为要求Scala 2.10:
// Implicit value class
implicit class Castable(val obj: AnyRef) extends AnyVal {
def asInstanceOfOpt[T <: AnyRef : ClassTag] = {
obj match {
case t: T => Some(t)
case _ => None
}
}
}
这可以通过以下方式使用:
"Hello".asInstanceOfOpt[String] == Some("Hello") // true
"foo".asInstanceOfOpt[List[_]] == None // true
然而,正如其他答案中所提到的,由于拳击问题,这不适用于原语,也不会因擦除而处理泛型。为了禁止原语,我限制 obj
和 T
来扩展 AnyRef
。对于处理原语的解决方案,请参阅Matt R后续问题的答案:
如何编写asInstanceOfOpt [T]其中T&lt ;: Any 一>
或者使用 shapeless 的Typeable,它处理原语以及许多擦除案例:
在编写oxbow_lakes的答案(09年末)时,我相信 scala.util.Try
不可用,但是,现在(即从2.10开始)我认为 scala.util.Try
是这种方式的首选(或者至少看起来更漂亮):
scala> Try((3).asInstanceOf[String]).toOption
res0: Option[String] = None
scala> Try("hello".asInstanceOf[String]).toOption
res1: Option[String] = Some(hello)
不隶属于 StackOverflow