Ist groovys Erweiterungsmodul eine hybride Form der Java-Vererbungsfunktion? Warum muss das Erweiterungsmodul als statisch deklariert werden?Groovys Erweiterungsmodul im Vergleich zur Vererbung von Java
Antwort
Kurze Antwort ist ich denke ja. Es ist ein bisschen schwierig, klar zu antworten, da die Vererbung für die Erweiterungsmethoden vollständig von der Laufzeit (und dem statischen Compiler) übernommen wird. Als solches hat es nichts damit zu tun, wie Java Vererbung macht.
Um die zweite Frage zu beantworten ... Sie sind statisch, weil für Situationen, in denen Sie Status benötigen Sie normalerweise die Meta-Klasse verwenden. Erweiterungsmethoden werden zunächst als Convenience-Methoden oder als Groovy-API betrachtet. Als solche sind sie eine spezielle Form von Methoden, die der Meta-Klasse hinzugefügt werden. Sie können sie als vereinfachte Version sehen. Das bedeutet aber auch, dass sie nicht alle Fähigkeiten haben. Das Implementieren von Erweiterungsmethoden, die den lokalen Zustand auf einer "Selbst" -Objektbasis halten können (im Grunde was Felder/Eigenschaften tun würden) ist tatsächlich schwierig effizient zu machen ... aber Sie könnten immer dafür pro Instanz Metaklassen verwenden.
Für alle umfangreichen Zwecke sind sie syntaktische Zucker, so dass eine statische Methode scheint mehr OOP wie. Es gibt keine Vererbung, da statische Methoden in Java und Groovy nicht an der Vererbung teilnehmen (dh Klassen erben keine statischen Methoden).
Die Methoden müssen statisch sein, da der Compiler nicht weiß, wie die umgebende Klasse der Erweiterungsmethode instanziiert wird.
Allerdings glaube ich, dass es Sprachen gibt, die erlauben, dass Methoden außerhalb der umschließenden Klasse definiert werden können und irgendeine Sortierung vererbt wird, aber nicht viele nicht (ich glaube, CLOS und Dylan tun das). Es gibt auch viele Sprachen, in denen Methoden hinzugefügt werden können, aber der Typ des "Objekts" wird tatsächlich auf einen anderen Typ geändert. Dies wird Ad-hoc-Polymorphismus genannt (z. B. Clojure, Haskell, eine Art Golang und eine Art Scala), hat aber wiederum nichts mit inklusivem Polymorphismus (Java-Vererbung) zu tun.
Leider ist die reference documentation und andere Dokumente definieren nicht die Semantik der Erweiterungsmethoden:
- Q. Können sie Instanzmethoden außer Kraft setzen?
Ich testete Erweiterung Methoden überuse
Kategorie Methoden undmetaClass
expando Methoden. Keines der beiden Verfahren überschreibt Instanzmethoden. Ich habe extension modules nicht getestet über module descriptor installiert. - Q. Können sie durch Erweiterungsmethoden für Unterklassen überschrieben werden?
Ich habe das auch getestet.use
Methoden undmetaClass
Erweiterungsmethoden werden nicht durch Erweiterungsmethoden für Unterklassen überschrieben. - Q. Können sie vererbte
super
Methoden aufrufen?
Nein, da sie überstatic
Methoden implementiert sind. - Q. Können sie private Methoden aufrufen?
Experimente zeigten, dass sie, überraschend. - Q. Können sie auf private Instanzvariablen zugreifen?
Nein, da sie überstatic
Methoden implementiert sind. - Q. Sind sie von Java-Methoden aufrufbar?
Vielleicht, if the extension module is on the classpath beim Kompilieren der aufrufenden Code. Ich habe es nicht getestet.
Fazit:Erweiterungsmethoden sind nicht eine Form der Vererbung. Sie scheinen eine dynamische Form von Universal Function Call Syntax (UFCS) zu sein, das heißt, wenn die Sprache keine Methode variable.foo(arguments)
finden kann, sucht es nach einer statischen Erweiterungsfunktion foo(variable, arguments)
zu rufen. [Bitte korrigieren Sie meine Hypothese, wenn falsch!]
Sie gefragt, warum sie als static
definiert sind. Das scheint die Semantik entsprechen: Eine statische Funktion, die ist nicht in Vererbung beteiligt, obwohl seine Aufrufsyntax es wie eine bequeme Methode Aufruf aussehen lässt.
Sie können eine Erweiterungsmethode wie eine Instanzmethode mit der @groovy.lang.Category Annotation schreiben. Das macht AST-Transformationen zur Kompilierzeit, um es in eine geeignete statische Methode umzuwandeln.
Siehe auch Groovy traits. Die ist eine Form von (mixin) Vererbung.
Denken Sie an Erweiterung Module in Bezug auf die Vererbung ist eine schlechte Idee. Sie erweitern eine bestimmte Klasse mit zusätzlichem Verhalten: Sie modifizieren also eine vorhandene Vererbungshierarchie, anstatt zu ihr beizutragen ... aber ihr Kontext ist wirklich auf eine einzelne Klasse ausgerichtet (ignorieren Sie also erneut die Vererbung). Andere Sprachen haben ein ähnliches Konstrukt als Teil der Erstklassentypdefinition (Go, Scala, Kotlin ...). Sie sind statisch, da sie außerhalb ihrer Laufzeitbindungsumgebung definiert sind. Stattdessen erhalten Sie die Instanz als Argument (wiederum ähnlich dem Ansatz anderer Sprachen). –