专业通用密封类型

时间:2011-10-15 19:55:31

标签: generics scala types

在Scala中,我希望能够像这样定义一般类型的抽象语法树节点

sealed abstract class AST[T <: AST[T]] {
    def child : List[T] ;
}

case class LeafAST[T <: AST[T]]( x : Int ) extends AST[T] {
    def child = Nil 
}

case class BranchAST[T <: AST[T]]( left : T, right : T ) extends AST[T] {
    def child = left :: right :: Nil
}

现在我可以编写像这样的通用代码

def countLeaves[T <: AST[T]]( x : AST[T]) : Int = x match {
    case LeafAST( x ) => 1
    case BranchAST( left, right ) => countLeaves[T](left) + countLeaves[T](right) 
}

现在我的第一个问题是关键字sealed似乎没有效果。如果我从匹配表达式中省略一个case,则没有错误。为什么以及如何写出我想要的东西? (我还有其他问题 - 比如如何专注于AST--但是我会在每篇文章中坚持一个问题。)

1 个答案:

答案 0 :(得分:0)

没有错误 - 有警告。例如:

scala> :paste
// Entering paste mode (ctrl-D to finish)

sealed abstract class AST[T <: AST[T]] {
    def child : List[T] ;
}

case class LeafAST[T <: AST[T]]( x : Int ) extends AST[T] {
    def child = Nil
}

case class BranchAST[T <: AST[T]]( left : T, right : T ) extends AST[T] {
    def child = left :: right :: Nil
}

// Exiting paste mode, now interpreting.

defined class AST
defined class LeafAST
defined class BranchAST

scala> def countLeaves[T <: AST[T]]( x : AST[T]) : Int = x match {
     |     case LeafAST( x ) => 1
     | }
<console>:10: warning: match is not exhaustive!
missing combination      BranchAST

       def countLeaves[T <: AST[T]]( x : AST[T]) : Int = x match {
                                                         ^
countLeaves: [T <: AST[T]](x: AST[T])Int

您可以使用标记-Xfatal-warnings将其变为错误。