Sie können jetzt Klassen im vorherigen Artikel "Unterstützung der Objekterstellung" laden. Ich möchte eine Klasse nutzen, die geladen werden kann, und statische Methodenaufrufe für diese Klasse verarbeiten.
Bestätigen Sie, dass Sie statische Methodenaufrufe unterstützen möchten.
Zum Beispiel gibt es das folgende Programm.
Die erste Zeile lädt die Klasse "Integer" in die Variable "integerClass".
Ich möchte, dass die zweite Zeile die statische Methode toHexString
dieser Klasse aufruft und ihren Rückgabewert ausgibt.
Die statische Methode toHexString
gibt die Argument-Ganzzahl als hexadezimale Zeichenfolge zurück.
Das Beispielargument lautet "255", daher lautet die Ausgabe "ff".
var integerClass = loadClass("java.lang.Integer")
println(integerClass.toHexString(255))
Lassen Sie uns darüber nachdenken, wie Sie es in Interpreter implementieren können. Es gibt keine Änderungen beim Phrasen-Parsing (Lexer) und beim syntaktischen Parsing (Parser).
Im vorherigen Artikel "Support-Methodenaufrufe" wurden Instanzmethodenaufrufe unterstützt. Da die Syntax der statischen Methode mit der der Instanzmethode identisch ist, entspricht der entsprechende Teil der der Instanzmethode.
Um es zu implementieren, beziehen Sie sich auf den Typ von "v", wenn ein Methodenaufruf wie "v.method ()" vorhanden ist. Es wird getrennt, ob es sich um einen Instanzmethodenaufruf oder einen statischen Methodenaufruf handelt. Wenn der Typ von "v" "Klasse <?>" Ist, wird dies als statischer Methodenaufruf angesehen. Jeder andere Typ wird als Instanzmethodenaufruf betrachtet. Andere Typen sind beispielsweise "String" und "Integer".
Fahren Sie mit der Implementierung fort. Werfen wir einen Blick auf die am Interpreter vorgenommenen Änderungen.
Interpreter.java
Eine Implementierung von Interpreter.java.
Dies ist eine Modifikation der Methode func ()
.
Die Methode func ()
garantiert, dass das Argument value
wie eine Funktion aufgerufen werden kann.
Geändert, um "if" -Anweisung unter "// Update" zu setzen.
Das v
im vorherigen Beispiel v.method ()
ist d.left
.
Holen Sie sich den Typ von v
mit d.left.getClass ()
.
Wenn der Typ von "v" "Klasse <?>" Ist, wird er als statischer Methodenaufruf betrachtet, andernfalls wird er als Instanzmethodenaufruf betrachtet.
Die if-Anweisung bestimmt, was dem Feld mf der Variablen vom Typ MethodFunc zugewiesen werden soll.
Wenn Sie die Werte für das Feld "mf" korrekt vorbereiten können, ist Ihnen der Unterschied zwischen statischen Methodenaufrufen und Instanzmethodenaufrufen nicht bekannt.
Dies liegt daran, dass der Methodenaufruf von der Methode "invoke" der Klasse "MethodFunc" ausgeführt werden kann.
Wenn die if
-Anweisung wahr ist, dh ein statischer Methodenaufruf, wird d.left
selbst mf.class_
zugewiesen.
Dies liegt daran, dass d.left
selbst den Typ darstellt.
null
wird mf.target
zugewiesen.
Das Zuweisen von "null" erfolgt, weil es sich um einen statischen Methodenaufruf handelt und keine Instanz zum Aufrufen der Methode erforderlich ist.
Wenn die if-Anweisung false ist, dh ein Instanzmethodenaufruf, bleibt sie dieselbe wie im vorherigen Methodenaufruf implementiert.
Interpreter.java
public Func func(Object value) throws Exception {
if (value instanceof Func) {
return (Func) value;
} else if (value instanceof Dotted) {
Dotted d = (Dotted) value;
MethodFunc mf = new MethodFunc();
mf.name = d.right.value;
// Update
Class<?> c = d.left.getClass();
if (c == Class.class.getClass()) {
mf.class_ = (Class<?>) d.left;
mf.target = null;
} else {
mf.class_ = c;
mf.target = d.left;
}
return mf;
} else if (value instanceof Variable) {
Variable v = (Variable) value;
return func(v.value);
} else {
throw new Exception("Not a function");
}
}
Das ist alles für die wichtigsten Änderungen.
Das folgende Programm verwendet die obige Implementierung
var integerClass = loadClass("java.lang.Integer")
println(integerClass.toHexString(255))
Ausgabe der hexadezimalen Darstellung ff
von 255
.
Interpreter.java
public static void main(String[] args) throws Exception {
String text = "";
text += "var integerClass = loadClass(\"java.lang.Integer\")";
text += "println(integerClass.toHexString(255))";
List<Token> tokens = new Lexer().init(text).tokenize();
List<Token> blk = new Parser().init(tokens).block();
new Interpreter().init(blk).run();
// --> ff
}
Das ist alles für die Implementierung. Vielen Dank.
Die vollständige Quelle finden Sie hier.
Calc https://github.com/quwahara/Calc/tree/article-20-static-method-invocation/Calc/src/main/java
Es gibt einen Folgeartikel.
** Laden Sie das Skript aus einer Datei und führen Sie es aus ** http://qiita.com/quwahara/items/bac43cd1df11b025e46a
Recommended Posts