Ich frage mich, ob der Compiler zur Kompilierungszeit für diesen bestimmten Patternmatch nicht weiß, welche möglichen Implementierungen dieses Merkmals / dieser Klasse verfügbar sind, wenn ich ein nicht versiegeltes trait
oder abstract class
in Scala verwendetes Muster verwende und dann den Mustervergleich verwende. Wenn dies der Fall ist, könnte es dann keine Warnungen vor Musterübereinstimmungen geben, obwohl das trait
/ abstract class
nicht versiegelt ist, weil er weiß, welche Typen verwendet werden könnten , indem alle möglichen Abhängigkeiten / Importe überprüft werden?
Wenn ich zB ein habe Option[A]
und nur einen Mustervergleich für, Some[A]
aber nicht für mache, None
beschwert sich der Compiler, weil er Option
versiegelt ist.
Wenn der Compiler das nicht wissen / lösen kann, warum kann er es dann nicht? Und wenn der Compiler dies (theoretisch) kann, was sind die Gründe dafür, dass er in Scala nicht verwendet wird? Gibt es andere Sprachen, die dieses Verhalten unterstützen?
quelle
Foo
mit UnterklassenA
,B
undC
, und alle Ihre Musterübereinstimmungen stimmen nur mit diesen drei überein. Nichts hindert mich daran, eine neue Unterklasse hinzuzufügenD
, die Ihre Musterübereinstimmungen in die Luft jagt.java.lang.ClassLoader
.Antworten:
Das Herausfinden aller Unterklassen einer Klasse wird als Klassenhierarchieanalyse bezeichnet. Das Ausführen einer statischen CHA in einer Sprache mit dynamischem Code-Laden entspricht der Lösung des Halteproblems.
Außerdem ist eines der Ziele von Scala die separate Kompilierung und Bereitstellung unabhängiger Module, sodass der Compiler einfach nicht wissen kann, ob eine Klasse in einem anderen Modul untergeordnet ist oder nicht, da nie mehr als ein Modul betrachtet wird. (Schließlich können Sie ein Modul gegen die Schnittstelle eines anderen Moduls kompilieren, ohne dass dieses Modul überhaupt auf Ihrem System vorhanden ist!) Aus diesem Grund
sealed
müssen alle Unterklassen in derselben Kompilierungseinheit definiert sein.Dies ist auch einer der Gründe, warum JVMs so günstig mit C ++ - Compilern konkurrieren können: C ++ - Compiler sind in der Regel statische Compiler, sodass sie im Allgemeinen nicht herausfinden können, ob eine Methode überschrieben wird oder nicht, und sie daher nicht einbinden können. JVMs OTOH sind normalerweise dynamische Compiler. Sie müssen keine CHA ausführen, um herauszufinden, ob eine Methode überschrieben wird oder nicht. Sie können sich zur Laufzeit nur die Klassenhierarchie ansehen. Und selbst wenn zu einem späteren Zeitpunkt in der Ausführung des Programms eine neue Unterklasse hinzukommt, die vorher nicht vorhanden war, keine große Sache, kompilieren Sie einfach diesen Code ohne Inlining neu.
Hinweis: All dies gilt nur innerhalb von Scala. Die JVM hat keine Ahnung davon
sealed
, daher ist es durchaus möglich,sealed
Klassen aus einer anderen JVM-Sprache zu unterordnen, da es keine Möglichkeit gibt, dies einer anderen Sprache mitzuteilen. Diesealed
Eigenschaft wird in derScalaSig
Annotation aufgezeichnet , aber die Compiler anderer Sprachen berücksichtigen diese Annotationen offensichtlich nicht.quelle
Es kann durchgeführt werden (zumindest für alle Klassen, die zur Kompilierungszeit bekannt sind), es ist nur teuer. Sie würden die inkrementelle Kompilierung vollständig zerstören, da alles, was eine Musterübereinstimmung enthält, bei jeder Änderung einer anderen Datei neu kompiliert werden müsste.
Und was kaufst du? Es ist ein Codegeruch, Musterübereinstimmungen zu schreiben, die sich häufig ändern müssen, wenn eine neue abgeleitete Klasse hinzugefügt wird. Es ist eine Verletzung des Open / Closed-Prinzips . Verwenden Sie die Vererbung richtig und Sie müssen diese Art von Musterübereinstimmungen nicht schreiben. Und ja, das Open / Closed-Prinzip gilt auch für funktionale Sprachen ohne klassenbasierte Vererbung. Tatsächlich erleichtern funktionale Sprachen zwischen Funktionen wie Typklassen, Multimethoden und einfachen Funktionen höherer Ordnung die Erweiterung ohne Änderung erheblich.
quelle
It can be done (at least for all classes known at compile time), it's just expensive.
Aber wenn das Programm nicht zu 100% in sich geschlossen ist (dh von externen.jar
Dateien abhängt ), können Sie sich nach dem Kompilieren durch eines derjar
s nicht in eine neue Unterklasse einschleichen ? Der Compiler könnte Ihnen also sagen, dass "Ihre Musterübereinstimmungen jetzt vollständig sind, aber das kann sich ändern, wenn sich eine Ihrer Abhängigkeiten ändert", was ziemlich wertlos ist, da der Sinn externer Abhängigkeiten darin besteht, sie ohne erneutes Kompilieren aktualisieren zu können!