2012-10-03 19 views
8

que tienen una clase de caso como el siguiente:Scala patrón de tipificación de pato juego

// parent class 
sealed abstract class Exp() 

// the case classes I want to match have compatible constructors 
case class A (a : Exp, b : Exp) extends Exp 
case class B (a : Exp, b : Exp) extends Exp 
case class C (a : Exp, b : Exp) extends Exp 

// there are other case classes extending Exp that have incompatible constructor, e.g. 
//  case class D (a : Exp) extends Exp 
//  case class E() extends Exp 
// I don't want to match them 

Quiero coincidir:

var n : Exp = ... 
n match { 
    ... 
    case e @ A (a, b) => 
     foo(e, a) 
     foo(e, b) 
    case e @ B (a, b) => 
     foo(e, a) 
     foo(e, b) 
    case e @ C (a, b) => 
     foo(e, a) 
     foo(e, b) 
    ... 
} 

def foo(e : Exp, abc : Exp) { ... } 

hay una manera de fusionar que tres casos en un solo caso (sin agregar una clase primaria intermedia a A, B, C)? No puedo cambiar la definición de A, B, C o Exp. Una especie de:

var n : Exp = ... 
n match { 
    ... 
    case e @ (A | B | C) (a, b) => // invalid syntax 
     foo(e, a) 
     foo(e, b) 
    ... 
} 

que, obviamente, no funciona, y tampoco lo hacen:

var n : Exp = ... 
n match { 
    ... 
    case e @ (A (a, b) | B (a, b) | C (a, b)) => // type error 
     foo(e, a) 
     foo(e, b) 
    ... 
} 

Respuesta

11

Aunque la siguiente "solución" es en realidad una forma diferente de escribir lo que ya tiene, podría ayudar si necesita utilizar el mismo match en más de un lugar y desea evitar la duplicación de código.

El siguiente encargo cancelar la aplicación:

object ExpABC { 
    def unapply(e:Exp):Option[(Int, Int)] = e match { 
     case A(a, b) => Some(a, b) 
     case B(a, b) => Some(a, b) 
     case C(a, b) => Some(a, b) 
     case _ => None 
    } 
} 

le permite escribir

n match { 
    case e @ ExpABC(a, b) => 
     println(e) 
     println(a) 
     println(b) 
} 

De esta manera no es necesario modificar las clases originales en absoluto. No conozco una forma mejor de hacer esto que no implique modificar las clases A/B/C, pero estoy ansioso por aprender @ Stackoverflow;)

Cuestiones relacionadas