2012-08-16 15 views
17

I tienen la siguiente jerarquía de clases:Scala - patrón de coincidencia de una tupla de tipos relacionados

class A 
class B extends A 
class C extends A 

a continuación, hay otra clase que tiene instancias de estas clases y hay un método, en el que dos casos de reconocimiento de patrones son posibles de esta manera:

class D (one: A, two: A) { 

    def work { 
    (one, two) match { 
     case (o, t): (B, B) => ... blablabla 
     case (o, t): (B, C) => ... blablabla 
     case _ => 
    } 
    } 
} 

Sin embargo, cuando debería resolver el juego a favor de la segunda caja (B, C), intenta resolver como (B, B) y viene con la excepción de difusión clase que C cannot be cast to B. ¿Por qué? ¿Qué hacer? ¿Cómo puedo superar esto?

Respuesta

26

Su sintaxis no es del todo correcta (no compila).

Esto funciona sin embargo:

object Matcher extends App { 

    class A 
    class B extends A 
    class C extends A 

    class D(one: A, two: A) { 

    def work { 
     (one, two) match { 
     case (o: B, t: B) => println("B") 
     case (o: B, t: C) => println("C") 
     case _ => 
     } 
    } 
    } 

    val d1 = new D(new B, new B) 
    val d2 = new D(new B, new C) 

    d1.work 
    //B 
    d2.work 
    //C 
} 
+0

He estado luchando tanto tiempo para descubrir la sintaxis correcta ... ¡Gracias! – Benoit

2

He hecho que este código funcione.
Primero agregué un caso a su definición de clase.

case class A 
case class B extends A 
case class C extends A 

En segundo lugar, cambié el work.

class D(one: A, two: A) { 
    def work { 
    (one, two) match { 
     case (o: B, t: B) => println("BB") 
     case (o: B, t: C) => println("BC") 
     case (o: C, t: C) => println("CC") 
     case _ => println("AA") 
    } 
    } 
} 

Ahora lo que tengo:

new D(B(),B()).work  => BB 
new D(B(),C()).work  => BC 
new D(C(),C()).work  => CC 
new D(A(),B()).work  => AA 

El case añade un aplique y un método de cancelar la aplicación.

+0

Sí, clases de casos ... pero tienen errores con la herencia ... Estaré muy feliz si lo arreglan en algún momento ... – noncom

+0

Estoy completamente contigo. –

+1

Este código no se compilará en Scala moderno, porque la herencia de casos está prohibida desde 2.9, creo. @noncom Esto no es un error, esto es por diseño –

7

El problema, como siempre, se borra tipos. (B,C) es azúcar sintáctica para Tuple2[B,C], que se borra a Tuple2 en tiempo de ejecución. El enunciado de caso verifica que (B,C) coincide con Tuple2, pero luego no puede emitirlo.

En su caso, la solución más fácil sería para que coincida contra el 'uno' y 'dos' de forma individual, en lugar de envolverlos en una tupla:

one match { 
    case o : B => two match { 
    case p : C => ... 
    case p : B => ... 
    } 
    ... 
} 

No es tan bonito, pero no lo hará sufren los mismos problemas

Editar: En realidad, yo iría con la solución de Brian Smith - haciendo coincidir dentro de la tupla en lugar de fuera. Evita el problema de forma similar, pero se ve mejor.

Cuestiones relacionadas