У меня есть простая иерархия классов, которая представляет собой графоподобную структуру с несколькими различными типами вершин, реализованными с использованием классов case:
sealed trait Node
sealed abstract case class Vertex extends Node
case class Arc extends Node
case class VertexType1 (val a:Int) extends Vertex
case class VertexType2 (val b:Int) extends Vertex
Это позволяет мне писать блоки совпадений следующим образом:
def test (x: Node) = x match {
case _ : Arc => "got arc"
case _ : Vertex => "got vertex"
}
или как это:
def test (x: Node) = x match {
case _ : Arc => "got arc"
case c : Vertex => c match {
case _ : VertexType1(a) => "got type 1 vertex " + a
case _ : VertexType2(a) => "got type 2 vertex " + a
}
}
Обратите внимание, что эта реализация имеет следующие свойства:
1) Позволяет записывать блоки соответствия, которые различают дуги и вершины, но не между конкретными типами вершин, но также и блоки соответствия, которые различают типы вершин.
2) В блоках сопоставления, характерных как для типа вершины, так и для типа, отличного от типа вершины, проверяется полнота сопоставления с образцом.
Однако наследование от case-классов устарело, и компилятор предлагает вместо этого использовать экстракторы для поддержки сопоставления на неконечных узлах (т. Е. В приведенном выше примере, чтобы различать дуги и вершины, но не типы вершин).
Вопрос: возможно ли реализовать аналогичную иерархию классов, не используя наследование классов дел, но при этом все еще имея проверки исчерпываемости шаблонов, выполняемые компилятором в обоих случаях использования, показанных выше?
РЕДАКТИРОВАТЬ : Я добавил параметр конструктора в классы VertexType, чтобы сопоставление не выполнялось только для типов.
Моя текущая реализация без классов case выглядит следующим образом:
sealed trait Node
sealed abstract class Vertex extends Node
class Arc extends Node
class VertexType1 (val a:Int) extends Vertex
class VertexType2 (val b:Int) extends Vertex
object VertexType1 {
def unapply (x : VertexType1) : Some[Int] = Some(x.a)
}
object VertexType2 {
def unapply (x : VertexType2) : Some[Int] = Some(x.b)
}
И тестовый код:
def test (x: Node) = x match {
case _ : Arc => "got arc"
case v : Vertex => v match {
case VertexType1(a) => "got vertex type 1 " + a
}
}
Я ожидаю предупреждения о неисчерпывающем совпадении во втором блоке (VertexType2 никогда не сопоставляется), но его нет.
На самом деле, компиляторы Scala до 2.9.0-RC3 выдают предупреждение, которое я ожидаю увидеть, но версии, начинающиеся с RC3 (включая 2.9.0 и 2.9.0-1), этого не делают, что довольно запутанно.