2012-06-27 11 views
11
sealed class A 
class B1 extends A  
class B2 extends A 

Suponiendo que tenemos una lista de objetos de la clase A: val l: Listado [A] = Lista (nueva B1, nueva B2, nueva B1, nueva B1)Cuándo usar isInstanceOf y cuándo usar una instrucción match-case (en Scala)?

Y queremos filtrar el elementos del tipo B1. entonces tenemos un predicado y podrían utilizar las siguientes dos alternativas:

l.filter(_.isInstanceOf[B1]) 

O

l.filter(_ match {case b: B1 => true; case _ => false}) 

Personalmente, me gusta el primer enfoque más, pero Leo a menudo, se debe utilizar la instrucción match-case más a menudo (por razones que no sé).

Por lo tanto, la pregunta es: ¿Hay inconvenientes de usar isInstanceOf en lugar de la instrucción match-case? ¿Cuándo se debe usar qué enfoque (y qué enfoque se debe usar aquí y por qué)?

Respuesta

17

Puede realizar un filtrado así:

l.collect{ case x: B1 => x } 

Eso es mucho más fácil de leer, la OMI.

+3

Y le da el tipo más angosto al final ('Lista [B1]'). –

+0

Parece mucho más legible, gracias.Pero, ¿cuál será el caso predeterminado en esta declaración? ¿Dónde puedo leer más información de contexto sobre esta declaración de caso de acceso directo y cómo se usa? –

+0

@JohnThreepwood echa un vistazo a [esta publicación] (http://ochafik.com/blog/?p=393). No es el mejor, pero sigue siendo bastante bueno "the why of collect". En breve, recopilar es como un mapa, pero haga un trabajo solo para aquellos valores definidos para la función * (parcial) * que pasa a este método. La coincidencia de patrones de Scala en este caso se realiza en la parte superior de [PartialFunction] (http://stackoverflow.com/questions/5668053/scala-partial-functions). Además, debe usar corchetes. –

7

No hay diferencia

t.scala gato:

class A { 
    def x(o: AnyRef) = o.isInstanceOf[A] 
    def y(o: AnyRef) = o match { 
    case s: A => true 
    case _ => false 
    } 
} 

$ scalac -print t.scala

[[syntax trees at end of cleanup]]// Scala source: t.scala 
package <empty> { 
    class A extends java.lang.Object with ScalaObject { 
    def x(o: java.lang.Object): Boolean = o.$isInstanceOf[A](); 
    def y(o: java.lang.Object): Boolean = { 
     <synthetic> val temp1: java.lang.Object = o; 
     temp1.$isInstanceOf[A]() 
    }; 
    def this(): A = { 
     A.super.this(); 
    () 
    } 
    } 
} 
+0

Genial, gracias por la información de fondo que hará el compilador scala. –

9

La ventaja de match-case es que no lo hace tiene que lanzar el objeto en caso de que quiera realizar operaciones en él que dependen de su tipo más estrecho.

En el siguiente fragmento, utilizando isInstanceOf parece estar bien, ya que no se realiza ninguna operación de este tipo:

if (obj.isInstanceOf[A]) println(obj) 

Sin embargo, si lo hace lo siguiente:

if (obj.isInstanceOf[A]) { 
    val a = obj.asInstanceOf[A] 
    println(a.someField) // someField is declared by A 
} 

entonces yo' estaríamos a favor de usar match-case:

obj match { 
    case a: A => println(a.someField) 
    case _ => 
} 

está un poco molesta ción que tiene que incluir la -case "de otro modo", pero utilizando collect (como insinuado por OM-nom-nom) podría ayudar, al menos si se trabaja con colecciones hereda de Sec:

collectionOfObj.collect{ case a: A => a}.foreach(println(_.someField)) 
+0

Gracias por sus buenos ejemplos, muy agradable. –

9

No hay problema al usar isInstanceOf, siempre que no use asInstanceOf.

El código que utiliza ambos es quebradizo, porque el control y la fundición son acciones separadas, mientras que al usar la coincidencia tiene una sola acción para ambos.

+0

Gracias por la pista, voy a tener cuidado con eso. –

Cuestiones relacionadas