Austauschen Fall Klasse Vererbung mit Abzieher Erhaltung Vollständigkeit überprüft, in Scala

Habe ich eine einfache Klassenhierarchie repräsentiert einen Graphen-ähnliche Struktur mit mehreren verschiedenen Arten von Knoten implementiert unter Verwendung von case-Klassen:

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

Dies ermöglicht mir, zu schreiben, entsprechen Sie Blöcke wie diese:

def test (x: Node) = x match {
  case _ : Arc => "got arc"
  case _ : Vertex => "got vertex"
}

oder so:

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
  }
}

Beachten Sie, dass diese Implementierung hat folgende Eigenschaften:

1) Es ermöglicht das schreiben von Spiel-Blöcke, unterscheiden zwischen Bögen und Ecken, aber nicht zwischen bestimmten vertex-Typen, aber auch match-Blöcke, die Unterscheidung zwischen Knoten-Typen.

2) In beiden vertex-Typ-spezifische und nicht-vertex-Typ-spezifische match-Blöcke der Vollständigkeit des pattern-matching überprüft.

Jedoch die Vererbung von case-Klassen ist veraltet, und der compiler legt Abzieher verwenden Sie stattdessen zur Unterstützung der Abgleich auf nicht-Blatt-Knoten (d.h., in dem obigen Beispiel, zu unterscheiden zwischen Bögen und Ecken, aber nicht zwischen Knoten-Typen).

Die Frage: ist es möglich zu implementieren, die eine ähnliche Klassenhierarchie ohne mithilfe der Klasse Vererbung, aber immer noch Muster der Vollständigkeit Prüfungen durch den compiler in beiden Fällen verwenden, die oben gezeigt?

BEARBEITEN: ich habe einen Konstruktor-parameter, um die VertexType Klassen, so dass das Spiel nicht durchgeführt, nur auf Arten.

Meine aktuelle Umsetzung, ohne den Fall Klassen ist wie folgt:

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)
}

Und den test-code:

def test (x: Node) = x match {
  case _ : Arc => "got arc" 
  case v : Vertex => v match {
    case VertexType1(a) => "got vertex type 1 " + a 
  }
}

Erwarte ich eine Warnung über nicht vollständige übereinstimmung in dem zweiten block (VertexType2 wird nie erreicht), aber gibt es nicht.

Eigentlich, Scala-Compiler vor 2.9.0-RC3 produzieren eine Warnung, die ich erwarte, um zu sehen, aber-Versionen ab RC3 (einschließlich 2.9.0 und 2.9.0-1) nicht, die ist eher verwirrend.

  • Nur der Vollständigkeit halber: das Problem wurde behoben in Scala 2.10. (es wurde eine regression in Scala 2.9.x)
Schreibe einen Kommentar