Ersetzen der Fallklassenvererbung durch Extraktoren, die Vollständigkeitsüberprüfungen in Scala erhalten

9

Ich habe eine einfache Klassenhierarchie, die eine graphartige Struktur mit mehreren unterschiedlichen Arten von Scheitelpunkten darstellt, die mit Fallklassen implementiert sind:

%Vor%

Dies ermöglicht mir das Schreiben von Match-Blöcken wie folgt:

%Vor%

oder wie folgt:

%Vor%

Beachten Sie, dass diese Implementierung die folgenden Eigenschaften aufweist:

1) Es ermöglicht das Schreiben von Match-Blöcken, die zwischen Bögen und Scheitelpunkten unterscheiden, aber nicht zwischen bestimmten Scheitelpunkttypen, sondern auch Blöcke, die zwischen Scheitelpunkttypen unterscheiden.

2) Sowohl in Vertextyp-spezifischen als auch in Nicht-Vertex-Typ-spezifischen Anpassungsblöcken wird die Vollständigkeit der Musterübereinstimmung überprüft.

Die Vererbung von Fallklassen ist jedoch veraltet, und der Compiler schlägt vor, stattdessen Extraktoren zu verwenden, um das Anpassen auf Nicht-Blattknoten zu unterstützen (d. h. im obigen Beispiel zwischen Bögen und Vertices, aber nicht zwischen Vertextypen zu unterscheiden).

Die Frage: Ist es möglich, eine ähnliche Klassenhierarchie zu implementieren, ohne die Vererbung von Fallklassen zu verwenden, aber in beiden oben gezeigten Anwendungsfällen trotzdem Mustervollständigkeitsüberprüfungen durch den Compiler durchzuführen?

BEARBEITEN : Ich habe den VertexType-Klassen einen Konstruktorparameter hinzugefügt, sodass die Übereinstimmung nicht nur für Typen durchgeführt wird.

Meine aktuelle Implementierung ohne die Fallklassen ist wie folgt:

%Vor%

Und der Testcode:

%Vor%

Ich erwarte eine Warnung über nicht erschöpfende Übereinstimmung im zweiten Block (VertexType2 wird niemals abgeglichen), aber es gibt keine.

Tatsächlich erzeugen Scala-Compiler vor 2.9.0-RC3 eine Warnung, die ich erwarten würde, aber Versionen, die mit RC3 beginnen (einschließlich 2.9.0 und 2.9.0-1), tun dies nicht, was ziemlich verwirrend ist.

    
Ivan Poliakov 13.06.2011, 16:39
quelle

3 Antworten

2

Im Allgemeinen kann dies nicht gemacht werden.

Versiegelte Klassen sind ein Sonderfall (kein Wortspiel beabsichtigt), weil scalac zur Kompilierzeit weiß, wie viele Übereinstimmungen möglich sind.

Aber da Extraktoren Ihnen erlauben, beliebigen Code auszuführen und wegen des verdammten Halteproblems, gibt es keine Möglichkeit für den Compiler, in jedem Fall zu garantieren, dass Sie jeden Fall überprüfen. Überlegen Sie:

%Vor%

Dies ist nicht erschöpfend, da es keine Zahlen behandelt, die keine Vielfachen von 8 sind, aber der Compiler kann (ohne den Extraktor auf allen Int auszuführen) nicht ableiten, dass nur einige Werte vom Typ Int sind Vielfache von 8.

    
Bill 14.06.2011 13:24
quelle
2

Extraktoren geben Ihnen die Möglichkeit, sie in Mustervergleiche wie Fallklassen in scala zu verwenden, aber sie haben keine anderen Standardimplementierungen, die Sie bei der Verwendung des Fallmodifikators erhalten. Aber diese zusätzliche Implementierung (insbesondere die Implementierung von equals) macht die Vererbung von Fallklassen gefährlich und daher wurde sie veraltet.

Geschlossene Klassen sind jedoch ein orthogonales Feature, und Sie können sie verwenden, unabhängig davon, ob Sie eine Fallklasse oder einen Extraktor haben. Durch Verwendung von Extraktoren erhalten Sie keine Standardimplementierungen im laufenden Betrieb, aber Sie können Vererbung von Extraktoren haben - es sind einfach normale Klassen mit einer unapply und / oder unapplySeq Methode.

Was Sie in Ihrem Beispiel getan haben, wird Mustererkennung für Typen genannt. Wenn Sie das nur tun wollen, brauchen Sie keine Fallklassen, keine Extraktoren. Du kannst es mit jeder gewünschten Klasse machen. Sie können den Case Modifier einfach entfernen.

Zum Schluss: Die Vollständigkeit des Musters wird durch versiegelte Klassenhirachien erreicht. Der Mustervergleich wird durch Extraktoren und Fallklassen erreicht, wobei letzterer nur ein Extraktor mit ansprechenden Standardimplementierungen häufig verwendeter Funktionen ist. Ich hoffe, das hat geholfen.

    
KIMA 13.06.2011 17:45
quelle
0

Das Zitat von scala-lang.org:

  

Wenn der Selektor einer Musterübereinstimmung eine Instanz einer versiegelten Klasse ist, kann die Kompilierung der Musterübereinstimmung Warnungen ausgeben, die diagnostizieren, dass eine gegebene Menge von Mustern nicht erschöpfend ist, dh dass die Möglichkeit besteht, dass MatchError beim Lauf ausgelöst wird -Zeit.

    
Jacek L. 13.06.2011 16:47
quelle