У меня есть простой класс иерархия, которая представляет графоподобную структуру с несколькими различными типами вершин, реализованных с использованием классов 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) Как в зависимости от типа вершины, так и без нее. -vertex-t Типичное совпадение блокирует, проверяется полнота сопоставления с образцом.
Однако наследование от классов 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) нет, что довольно сбивает с толку.