2012-04-25 9 views
8

Ich mag Scala isInstanceOf und asInstanceOf Methoden - sie sind lang und asInstanceOf kann Ausnahme auslösen, so dass wir es paar verwenden müssen. Ein besserer Weg ist der Mustervergleich: Scala: How do I cast a variable?, aber für wirklich einfache Operationen kann es auch relativ lang sein. In C# haben wir 'is' und 'as' Operatoren, also wollte ich implizite Definition damit in Scala implementieren. Mein Code sieht wie folgt aus:Scala kurze und typsichere Cast-Operator

scala> class TypeCast(x:Any){ 
    | def is[T](t:Class[T]) = t.isInstance(x) 
    | def as[T](t:Class[T]):Option[T] = if(t.isInstance(x)) Option(t.cast(x)) else None 
    | } 
defined class TypeCast 

scala> implicit def TypeCastID(x:Any)=new TypeCast(x) 
TypeCastID: (x: Any)TypeCast 

scala> 123 as classOf[String] 
res14: Option[String] = None 

scala> "asd" as classOf[String] 
res15: Option[String] = Some(asd) 

Es hat einen Vorteil - null-Objektmuster implementieren, aber auch Nachteile haben:

  • brauchen classof [T] Operator verwenden - es ist zu lang

  • Overhead mit impliziter def verbunden ist, um so einfacher Betrieb

so die Es gibt keinen praktischen Grund, es zu benutzen. Ich würde gerne wissen, gibt es eine Möglichkeit, dies zu implementieren, ohne die Verwendung von classOf [T]?

+2

Meiner Meinung nach zu vermeiden, ist es gut dass 'isInstanceOf' und' asInstanceOf' relativ lange und unbequeme Namen haben. Normalerweise sollten Sie die dynamische Typprüfung und das Casting vermeiden und stattdessen einen besseren OO-Stil-Ansatz (Polymorphismus) oder Mustervergleich (Funktionsstil) verwenden. Die unbequemen Namen ermutigen Sie, sie nicht zu oft zu benutzen. In Ihrem Titel fragen Sie nach einem "Typ Safe Cast Operator". Casting ist per Definition niemals typsicher. – Jesper

+0

Ich vermutete, dass es ähnliche Kommentare geben wird. Im Allgemeinen stimme ich Ihnen zu, dass gutes Design und Mustervergleich viel besser ist. Aber manchmal IMHO 'als' Notation ist viel kürzer und klarer. Zum Beispiel können wir eine Bibliothek von Dritten verwenden, wo das Design nicht so gut ist, wie wir es brauchen. Es gibt auch Option [T] statt T, also ist es sicherer. Und am Ende: Antwort auf diese Frage geben mir vor allem zusätzliches Wissen über Scala :) – theres

Antwort

10

Nun könnten Sie es innerhalb der Def, die Sie in der TypeCast-Klasse gemacht haben, kürzen. Anstatt einen Parameter einzugeben, können Sie sich einfach auf den Typ verlassen. Dies würde es sehr verkürzen. Als Beispiel aussehen könnte so etwas wie:

scala> 123.as[String] 
res0: Option[String] = Some(123) 
scala> class A; class B extends A 
defined class A 
defined class B 
scala> new B 
res1: B 
scala> res1.is[Int] 
res2: Boolean = false 
scala> res1.as[Int] 
res3: Option[Int] = None 

Update::

class TypeCast(x : Any) { 
    def is[T : Manifest] = manifest.erasure.isInstance(x) 
    def as[T : Manifest] : Option[T] = if (manifest.erasure.isInstance(x)) Some(x.asInstanceOf[T]) else None 
} 

Zukunft Anrufe aussehen könnte ich Manifests hinzugefügt Typ-Check Fehler

+0

Ich versuche ähnliche Lösung, aber das leider nicht richtig funktioniert: Klasse A; Klasse B erweitert A; val b = neu B; b.as [Int] geben mi Einige (instance-of-B) anstelle von keine und auch b.is [Int] return true – theres

+2

Es scheint, Sie können Manifeste verwenden, um Dinge zu klären .. Ich werde den Code aktualisieren . –

+0

Danke! Ich habe noch nie von Manifesten gehört. – theres