Замена наследования case-класса с сохранением экстракторов проверки полноты в Scala

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

9
задан tshepang 7 March 2014 в 08:29
поделиться