2012-04-25 14 views
8

No me gustan los métodos Scala isInstanceOf y asInstanceOf: son largos y asInstanceOf puede arrojar excepciones, por lo que debemos usarlo en pareja. La mejor forma es usar la coincidencia de patrones: Scala: How do I cast a variable? pero para operaciones realmente simples también puede ser relativamente larga. En C# tenemos operadores 'como' y 'como', así que quería implementar una definición implícita con esto en Scala. Mi mirada código como este:Scala short y type Operador de conversión segura

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) 

tiene una ventaja - implementar el patrón nula a objetos, pero también tienen desventajas:

  • necesidad de utilizar classof operador [T] - es demasiado larga

  • generales relacionados con la def implícito para tal operación simple

por lo que la re no hay razón práctica para usarlo. Me gustaría saber si hay alguna forma de implementar esto sin necesidad de usar classOf [T]?

+2

En mi opinión, es bueno que 'isInstanceOf' y' asInstanceOf' tienen nombres relativamente largos e inconvenientes. Por lo general, querrás evitar la verificación dinámica de tipos y el uso de un estilo de OO mejor (polimorfismo) o la coincidencia de patrones (estilo funcional). Los nombres inconvenientes lo alientan a no usarlos demasiado. En su título, está solicitando un "operador de tipo de transmisión segura". Casting nunca es seguro, por definición. – Jesper

+0

Supuse que habría comentarios similares. En general, estoy de acuerdo con usted en que el buen diseño y la coincidencia de patrones es mucho mejor. Pero a veces la notación 'como' en mi humilde opinión es mucho más corta y clara. Por ejemplo, podemos usar una biblioteca de terceros donde el diseño no es tan bueno como necesitamos. También devuelve la opción [T] en lugar de T para que sea más segura. Y al final: la respuesta a esta pregunta, sobre todo, me da un conocimiento adicional sobre Scala :) – theres

Respuesta

10

Bueno, podrías acortarlo dentro de la definición que hiciste en la clase TypeCast. Entonces, en lugar de alimentarlo con un parámetro, simplemente puedes confiar en el tipo. Esto lo acortaría mucho. A modo de ejemplo, esto podría parecer algo como:

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 
} 

llamadas futuro podría parecerse a:

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 

Actualización: He añadido manifiestos para evitar errores de tipo de verificación

+0

Intento una solución similar, pero desafortunadamente no funciona correctamente: clase A; clase B extiende A; val b = new B; b.as [Int] dar mi Some (instance-of-B) en lugar de None y también b.is [Int] return true – theres

+2

Parece que puede usar manifiestos para aclarar las cosas .. Actualizaré el código . –

+0

Gracias! Nunca escuché sobre Manifiestos antes. – theres

Cuestiones relacionadas