【问题标题】:Scala duck typing pattern matchingScala 鸭子类型匹配
【发布时间】:2012-10-04 01:52:49
【问题描述】:

我有一个类似下面的案例类:

// 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

我要匹配:

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) { ... }

有没有办法将这三个案例合并为一个案例(不向 A、B、C 添加中间父类)?我无法更改 A、B、C 或 Exp 的定义。某种:

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

这显然行不通,也不行:

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

【问题讨论】:

    标签: scala pattern-matching case-class


    【解决方案1】:

    虽然以下“解决方案”实际上只是编写已有内容的另一种方式,但如果您需要在多个地方使用相同的 match 并希望避免代码重复,它可能会有所帮助。

    以下自定义取消应用:

    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
        }
    }
    

    允许你写

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

    这样你根本不需要修改原来的类。我不知道不涉及修改 A/B/C 类的更好方法,但我很想学习 @Stackoverflow ;)

    【讨论】:

      猜你喜欢
      • 2011-08-25
      • 1970-01-01
      • 2013-12-21
      • 1970-01-01
      • 2012-08-27
      • 1970-01-01
      • 1970-01-01
      • 2015-05-21
      • 1970-01-01
      相关资源
      最近更新 更多