ケースクラスを使用して実装されたいくつかの異なるタイプの頂点を持つグラフのような構造を表す単純なクラス階層があります。
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) 頂点タイプ固有のマッチ ブロックと非頂点タイプ固有のマッチ ブロックの両方で、パターン マッチングの網羅性がチェックされます。
ただし、ケース クラスからの継承は非推奨であり、コンパイラは代わりにエクストラクタを使用して非リーフ ノードでのマッチングをサポートすることを提案します (つまり、上記の例では、アークと頂点を区別し、頂点タイプを区別しません)。
問題: ケース クラスの継承を使用せずに同様のクラス階層を実装することは可能ですが、上記の両方のユース ケースでコンパイラによってパターンの網羅性チェックが実行されますか?
編集: VertexType クラスにコンストラクター パラメーターを追加して、型に対してのみ一致が実行されないようにしました。
ケースクラスを使用しない現在の実装は次のとおりです。
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
}
}
2 番目のブロック (VertexType2 が一致することはありません) で非網羅的な一致に関する警告が表示されることを期待していますが、それはありません。
実際、2.9.0-RC3 より前の Scala コンパイラでは警告が表示されるはずですが、RC3 以降のバージョン (2.9.0 および 2.9.0-1 を含む) では警告が表示されず、かなり混乱しています。