斯卡拉的密封类

时间:2013-11-08 18:22:16

标签: scala functional-programming case-class traits

以下是我的代码段:

sealed abstract class Expr
case class Var(name: String) extends Expr
case class Number(num: Double) extends Expr
case class UnOp(operator: String, arg: Expr) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr

object CaseClassTest extends App {
    def simplifyExp(xs: Expr): Expr = xs match {
      case UnOp("-",UnOp("-", x)) => x
      case BinOp("+",x,Number(0)) => x
      case BinOp("*",x,Number(1)) => x
    }

    def describe(e: Expr): String = e match {
      case Number(_) => "Number"
      case Var(_) => "Var"
    } 
}

现在描述方法中发生的事情我收到一条警告,指出“匹配可能并不详尽。它会在以下输入上失败:BinOp(_,_,),UnOp(,_)“。它看起来非常适合我,因为我没有考虑像BinOp,UnOp这样的其他测试用例。完美

但是我的问题是为什么同样的警告不会出现在 def simplifyExp(xs:Expr):Expr ?有什么我想念的吗?感谢

2 个答案:

答案 0 :(得分:5)

simplifyExp的情况下,你使用提取器组合,我认为编译器不够聪明,无法检测到问题。

很明显,以下代码在运行时因MatchError

而失败
CaseClassTest.simplifyExp(Var("toto"))

答案 1 :(得分:0)

编译器显示真正的警告,因为simplifyExp无法处理Expr类型的所有参数。例如,做:

scala> simplifyExp(new Var("as"))
scala.MatchError: Var(as) (of class Var)
        at .simplifyExp(<console>:22)
        at .<init>(<console>:24)...

同样,它无法处理BinOp(_, _, _)类型的参数,即BinOp采用任何String,任何左Expr,右Expr。

关于第二个功能,更改声明的顺序,并显示describe的警告:

scala> object CaseClassTest extends App {
    def describe(e: Expr): String = e match {
      case Number(_) => "Number"
      case Var(_) => "Var"
    }

    def simplifyExp(xs: Expr): Expr = xs match {
      case UnOp("-",UnOp("-", x)) => x
      case BinOp("+",x,Number(0)) => x
      case BinOp("*",x,Number(1)) => x
    }

}
<console>:23: warning: match may not be exhaustive.
It would fail on the following inputs: BinOp(_, _, _), UnOp(_, _)
           def describe(e: Expr): String = e match {
                                           ^
defined module CaseClassTest

如果您在上述情况下更正了describe,那么它也会显示simplifyExpr