software - scala wikipedia
Cómo escribir "asInstanceOfOption" en Scala (3)
Aquí hay una explicación de la respuesta actualizada de oxbow_lake, más actualizada para requerir 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
}
}
}
Esto puede ser usado haciendo:
"Hello".asInstanceOfOpt[String] == Some("Hello") // true
"foo".asInstanceOfOpt[List[_]] == None // true
Sin embargo, como se mencionó en otras respuestas, esto no funciona para los primitivos debido a problemas de boxeo, ni maneja los genéricos debido al borrado. Para rechazar primitivas, restringí obj
y T
para extender AnyRef
. Para una solución que maneje primitivas, consulte la respuesta para la pregunta de seguimiento de Matt R:
Cómo escribir asInstanceOfOpt [T] donde T <: Cualquiera
O use Typeable sin forma, que maneja primitivas, así como muchos casos de borrado:
¿Es posible escribir un método "asInstanceOfOption" que haría lo que se pretende con el siguiente código (falso)?
def asInstanceOfOption[T](o: Any): Option[T] =
if (o.isInstanceOf[T]) Some(o.asInstanceOf[T]) else None
En el momento de escribir la respuesta de oxbow_lakes (finales de ''09), creo que scala.util.Try
no estaba disponible, sin embargo, ahora (es decir, a partir de 2.10) creo que scala.util.Try
es el preferido (o al menos mejor aspecto) forma de hacer esto:
scala> Try((3).asInstanceOf[String]).toOption
res0: Option[String] = None
scala> Try("hello".asInstanceOf[String]).toOption
res1: Option[String] = Some(hello)
EDITAR A continuación está mi respuesta original, pero puedes lograr esto ahora con
def asInstanceOfOption[T: ClassTag](o: Any): Option[T] =
Some(o) collect { case m: T => m}
Podría usar manifiestos para evitar el hecho de que el tipo T
se borra en tiempo de compilación:
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]
Entonces esto podría ser usado:
scala> asInstanceOfOption[Int]("Hello")
res1: Option[Int] = None
scala> asInstanceOfOption[String]("World")
res2: Option[String] = Some(World)
Incluso podrías usar conversiones implícitas para que esto sea un método disponible en Any
. Creo que prefiero el nombre del método 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
}
}
Ahora puedes escribir código como:
"Hello".matchInstance[String] == Some("Hello") //true
"World".matchInstance[Int] == None //true
EDITAR: código actualizado para 2.9.x, donde uno no puede usar Any
pero solo 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
}
}