2017-02-21 18 views
2

Я пытаюсь определить бинарное дерево со следующим определением:Scala шаблону с типом Option

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 

, а затем определить простой printTree метод с использованием шаблона в Scala соответствия, как показано ниже:

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 может иметь None или Some как его значения. В случае Option[Node] он может быть либо Some(LeafNode), либо Some(BranchNode). Какие еще случаи я не замечаю?

ответ

5

Поскольку ваш признак не является sealed, он открыт для расширения в разных пакетах. IntelliJ предупреждает вас о будущей возможности того, что любой, кто расширяет эту черту и забывает реализовать дополнительный case, может вызвать MatchError. Если вы хотите ограничить это расширение, используйте:

sealed trait Node 
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") 
} 
Смежные вопросы