Frage

Ist es möglich, eine „asInstanceOfOption“ Methode zu schreiben, das tun würde, was durch den folgenden (Schein-) Code bestimmt ist?

def asInstanceOfOption[T](o: Any): Option[T] =
   if (o.isInstanceOf[T]) Some(o.asInstanceOf[T]) else None 
War es hilfreich?

Lösung

Bearbeiten Unter meiner ursprünglichen Antwort ist, aber Sie können dies erreichen jetzt mit

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

Sie könnten Manifeste verwenden um die Tatsache zu bekommen, dass der Typ T ist gelöschter bei der Kompilierung:

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]

Dann ist diese verwendet werden könnte:

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

scala> asInstanceOfOption[String]("World")
res2: Option[String] = Some(World)

Sie können sogar verwenden implizite Konvertierungen zu bekommen dies eine Methode zur Verfügung, auf Any zu sein. Ich denke, ich ziehe die Methodennamen 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
  }   
}

Jetzt können Sie Code schreiben, wie:

"Hello".matchInstance[String] == Some("Hello") //true
"World".matchInstance[Int] == None             //true    

EDIT: aktualisierten Code für 2.9.x, wo man nicht Any aber nur AnyRef verwenden kann:

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
  }   
}

Andere Tipps

Hier ist eine Weiterentwicklung auf oxbow_lake aktualisierten Antwort, aktualisiert weiter erfordern 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
    }
  }
}

Dies kann dabei verwendet werden:

"Hello".asInstanceOfOpt[String] == Some("Hello") // true
"foo".asInstanceOfOpt[List[_]] == None // true

Doch wie in anderen Antworten erwähnt dies nicht funktioniert für Primitive wegen Boxen Probleme, noch nicht Generika handhaben, weil der Löschung. Um nicht zuzulassen Primitiven, beschränken ich obj und T AnyRef zu verlängern. Für eine Lösung, die Primitiven behandelt, beziehen sich auf die Antwort für Matt R Followup Frage:

Wie schreibt asInstanceOfOpt [T], wobei T <: Alle

oder benutzen formlos 's typisierbarer, die Primitiven sowie viele Löschungsfälle behandelt:

Typ Gießen Typparameter

Zum Zeitpunkt des Schreibens von oxbow_lakes Antwort (Ende '09), glaube ich scala.util.Try war nicht verfügbar, aber jetzt (dh ab 2.10) Ich denke, scala.util.Try ist die bevorzugte (oder auch zumindest besser aussehend) Art und Weise dies zu tun:

scala> Try((3).asInstanceOf[String]).toOption
res0: Option[String] = None

scala> Try("hello".asInstanceOf[String]).toOption
res1: Option[String] = Some(hello)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top