2012-04-25 15 views
8

Non mi piacciono i metodi Scala isInstanceOf e asInstanceOf: sono lunghi e asInstanceOf può generare eccezioni, quindi è necessario utilizzarlo in coppia. Il modo migliore è utilizzare la corrispondenza dei modelli: Scala: How do I cast a variable? ma per operazioni davvero semplici può essere anche relativamente lungo. In C# abbiamo operatori 'is' e 'as' quindi volevo implementare la definizione implicita con questo in Scala. Il mio codice simile a questa:Operatore per il cast di tipo short e type safe

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) 

ha un vantaggio - implementare modello null-oggetto, ma anche svantaggi:

  • bisogno di utilizzare classOf operatore [T] - è troppo lungo

  • testa collegata con def implicita per tale operazione semplice

così la non è una ragione pratica per usarlo. Mi piacerebbe sapere c'è un modo per implementarlo senza dover usare classOf [T]?

+2

A mio parere, è un bene that' isInstanceOf' e 'asInstanceOf' hanno nomi relativamente lunghi e scomodi. Normalmente vorrai evitare il controllo dinamico dei tipi e il cast e usare un approccio migliore stile OO (polimorfismo) o pattern matching (stile funzionale). I nomi scomodi ti incoraggiano a non usarli troppo. Nel tuo titolo stai chiedendo un "tipo di operatore cast sicuro". Il casting non è mai sicuro, per definizione. – Jesper

+0

Suppongo che ci sarà un commento simile. In generale sono d'accordo con te sul fatto che un buon design e l'abbinamento di modelli sono molto migliori. Ma a volte IMHO 'come' notazione è molto più breve e più chiara. Ad esempio, possiamo utilizzare la libreria di terze parti in cui il design non è buono come abbiamo bisogno. Restituisce anche Option [T] invece T così è più sicuro. E alla fine: rispondere a questa domanda mi dà più informazioni su Scala :) – theres

risposta

10

Bene, è possibile ridurlo all'interno della def che è stata creata nella classe TypeCast. Quindi, invece di alimentarlo, puoi semplicemente fare affidamento sul tipo. Questo lo ridurrebbe molto. A titolo di esempio, questo potrebbe somigliare:

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 
} 

chiamate futuro potrebbe essere simile:

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 

Aggiornamento: Ho aggiunto manifesti per evitare errori di tipo-check

+0

Provo una soluzione simile, ma sfortunatamente non funziona correttamente: classe A; la classe B estende A; val b = nuovo B; b.as [Int] restituiscono mi Some (instance-of-B) invece di None e anche b.is [Int] return true – theres

+2

Sembra che tu possa usare manifests per cancellare le cose .. Aggiorno il codice . –

+0

Grazie! Non ho mai sentito parlare dei Manifesti prima. – theres

Problemi correlati