Ich lese mich in Lisp, derzeit auf dieser Seite ( Ссылка ), und habe die folgende Aussage im vorletzten Absatz auf der Seite gefunden, die zeigt wann Klicken Sie auf den Link CLOS GUILD :
Es ist wichtig zu beachten, dass das CLOS die beiden in die Methode übergebenen Objekte berücksichtigen muss, um herauszufinden, welche Mischmethode in einer bestimmten Situation aufgerufen werden soll. Es wird auf eine bestimmte Implementierung der Methode basierend auf den Typen von multiplen Objekten verteilt. Dies ist eine Funktion, die in herkömmlichen objektorientierten Sprachen wie Java oder C ++ nicht verfügbar ist.
Hier ist der Beispiel-Lisp-Code:
%Vor%Nein, ich denke, dass der letzte Satz falsch ist. Genau das kann ich mit folgendem Java-Code machen:
%Vor%was mir die gleiche Ausgabe gibt, wenn ich es ausführe:
%Vor%Also meine Frage ist: Ist dieser Satz auf dieser Seite eigentlich falsch und ist es in Java / C ++ möglich? Wenn ja, war das vielleicht in einer älteren Version von Java nicht möglich? (Obwohl ich das sehr bezweifle, da das Buch erst 5 Jahre alt ist) Wenn nicht, was habe ich in meinem Beispiel vergessen?
Wenn Sie Ihr Beispiel ändern zu:
%Vor%dann werden Sie
bekommen %Vor%Java verwendet die Kompilierzeittypen, um herauszufinden, welche Überladung der aufzurufenden Methode von Lisp auf den Laufzeittypen ausgelöst wird. Java muss das Visitor-Muster verwenden, um einen doppelten Versand durchzuführen (Aufruf einer anderen Implementierung basierend auf dem Typ des Objekts, an dem die Methode aufgerufen wird, und dem Typ des übergebenen Arguments).
Sowohl C ++ als auch Java können Methoden mit mehreren Argumenten überladen, aber es ist statisch und nur für Methoden (die für Java Bürger zweiter Klasse unter den Klassen und Objekten sind). Es löst das Ausdrucksproblem nicht per se: Sie können keine neue Klasse mit einer neuen Reihe von unterstützten Kombinationen von Argumenten einführen und es mit den vorhandenen kombinieren lassen.
Sie können den von JVM unterstützten Reflektionsmechanismus verwenden und eine Klasse schreiben, die Methoden nach ihren Argumenten "registriert" und die Dispatch-Daten in einem Speicher für diese Klasse speichert. Reflektion, die hilft, die Arten von Argumenten abzuleiten, ist nicht der schnelle Weg, um in JVM zu versenden, aber wird wahrscheinlich benötigt, um generische Funktionen zu implementieren.
Der eigentliche Weg, den Sie in Java mit OO machen würden, wäre folgender:
%Vor% Wenn du dir nun vorstellst, dass Yellow
von dir gemacht wird, aber der Rest wird von jemand anderem gemacht. In CLOS können Sie (defmethod mix ((c2 red) (c1 yellow))
als Teil Ihrer Implementierung von yellow
angeben, aber wie liefern Sie die Überladung public void mix(Color c)
in class Blue
, um "you made orange!" ohne es zu ändern?
Sie erhalten ein besseres Bild vom folgenden Beispiel:
%Vor%Es sieht aus wie Überladen der Methode. Aber es gibt einen Unterschied: Wenn Sie dies tun (vorausgesetzt, "Person" ist die Oberklasse von Kunde, Benutzer und SuperUser):
%Vor%, dann wird sich der C # -Compiler beschweren, weil er nicht weiß, welche der drei Methoden er aufrufen soll. Wenn C # Multi-Methoden hätte, würde dies wie erwartet kompiliert und ausgeführt werden, dh der erste "Print" würde aufgerufen werden. Dies liegt daran, dass bei Multimethoden die dynamischen (Laufzeit) -Typen aller Argumente sind (nicht nur der erste) werden zur Laufzeit bei der Entscheidung, welche Methode zu rufen.
Der Aufruf von multimethod verwendet den Basistyp für die Argumente, findet jedoch immer noch die geeigneten Implementierungen für die abgeleiteten Typen.
Ich schätze, Sie sollten den folgenden Link lesen, um ein besseres Bild zu erhalten:
Der Unterschied besteht hier darin, dass Sie in Java für den Versand mit einem Argument normale Klassenmethoden verwenden (in der Klassendatei) und für viele andere Argumente eine Hilfsklasse (in einer eigenen Datei) verwenden, wie in Ihrem Beispiel . Und in CLOS ist es vereinheitlicht, Sie benutzen ein Formular für alles, was in Dateien aufgeteilt wird, die für Sie geeignet sind.
Tags und Links java class lisp clos multiple-dispatch