Scala模式与Option类型匹配

时间:2017-02-21 19:18:19

标签: scala pattern-matching

我正在尝试使用以下定义定义二叉树:

  trait Node {
    val label: Int
  }
  case class BranchNode(override val label: Int, left: Option[Node], right: Option[Node]) extends Node
  case class LeafNode(override val label: Int) extends Node

然后使用Scala的模式匹配定义一个简单的printTree方法,如下所示:

  def printTree(aTree: Option[Node]): Unit = aTree match {
    case None => print(".")
    case Some(LeafNode(label)) => print(label)
    case Some(BranchNode(label, left, right)) => "{" + printTree(left) + label + printTree(right) + "}"
  }

Intellij IDE警告我,这场比赛可能并非详尽无遗。 Option可以包含NoneSome个值。如果是Option[Node],则可以是Some(LeafNode)Some(BranchNode)。我还有什么其他情况可以忽略?

2 个答案:

答案 0 :(得分:6)

由于您的特征不是sealed,因此它可以在不同的包中进行扩展。 IntelliJ警告您,未来有可能延长此特性而忘记实施其他case的人可能会导致MatchError。如果要限制其扩展名,请使用:

sealed trait Node

答案 1 :(得分:3)

肯定是编译器警告,请参阅下面我通过传递printTree(Option(IWillBreakYou(2)))

来破坏您的代码

match error

      trait Node {
        val label: Int
      }
      case class BranchNode(override val label: Int, left: Option[Node], right: Option[Node]) extends Node
      case class LeafNode(override val label: Int) extends Node

      case class IWillBreakYou(override val label: Int) extends Node

      def printTree(aTree: Option[Node]): Unit = aTree match {
        case None => print(".")
        case Some(LeafNode(label)) => print(label)
        case Some(BranchNode(label, left, right)) => "{" + printTree(left) + label + printTree(right) + "}"
      }

      val leftNode = Option(LeafNode(2))
      val rightNode = Option(LeafNode(3))
      printTree(Option(BranchNode(1, leftNode, rightNode)))

      printTree(Option(IWillBreakYou(2))) //this will fail

原因是你正在使用Option[Node]并且任何人都可以延长Node(在包内/外,除非受到保护),你在比赛中没有考虑。

因此,添加故障安全匹配case _将解决未来的错误。

def printTree(aTree: Option[Node]): Unit = aTree match {
        case None => print(".")
        case Some(LeafNode(label)) => print(label)
        case Some(BranchNode(label, left, right)) => "{" + printTree(left) + label + printTree(right) + "}"
        case _ => println("do nothing")
 }