Die Programmiersprache Ruby (German Edition)
Reflexion und Metaprogrammierung
Wir haben gesehen, dass Ruby eine sehr dynamische Sprache ist; Sie können zur Laufzeit neue Methoden in Klassen einfügen, Aliase für bestehende Methoden erzeugen und sogar Methoden für individuelle Objekte definieren. Zusätzlich besitzt die Sprache eine reichhaltige API zur Reflexion . Reflexion, auch Introspektion genannt, bedeutet einfach, dass ein Programm seinen Zustand und seine Struktur untersuchen kann. Ein Ruby-Programm kann beispielsweise die Liste der von der Klasse
Hash
definierten Methoden erhalten, den Wert einer genannten Instanzvariablen innerhalb eines angegebenen Objekts ermitteln oder über alle derzeit vom Interpreter definierten
Regexp
-Objekte iterieren. Die Reflexions-API geht tatsächlich noch weiter und erlaubt einem Programm, seinen Zustand und seine Struktur zu ändern. Ein Ruby-Programm kann benannte Variablen dynamisch setzen, benannte Methoden aufrufen und sogar neue Klassen und neue Methoden definieren.
Die Reflexions-API der Sprache Ruby – gemeinsam mit ihrer allgemein dynamischen Natur, ihrer Block-und-Iterator-Kontrollstrukturen und ihrer Syntax mit optionalen Klammern – macht sie zu einer idealen Sprache für die Metaprogrammierung . Vage definiert ist Metaprogrammierung das Schreiben von Programmen (oder Frameworks), die Ihnen helfen, Programme zu schreiben. Anders ausgedrückt ist Metaprogrammierung ein Satz von Technologien, um Rubys Syntax auf eine Weise zu erweitern, die die Programmierung erleichtert. Metaprogrammierung ist eng mit der Idee des Schreibens domänenspezifischer Sprachen ( domain-specific languages oder DSLs) verbunden. DSLs in Ruby verwenden Methodenaufrufe und Blöcke normalerweise so, als seien sie Schlüsselwörter in einer aufgabenspezifischen Erweiterung der Sprache.
Dieses Kapitel beginnt mit diversen Abschnitten, die Rubys Reflexions-API vorstellen. Diese API ist überraschend reichhaltig und enthält eine Vielzahl von Methoden. Diese Methoden werden zum Großteil von
Kernel
,
Object
und
Module
definiert.
Während Sie diese einführenden Abschnitte lesen, sollten Sie bitte im Kopf behalten, dass Reflexion selbst noch keine Metaprogrammierung ist. Metaprogrammierung erweitert üblicherweise die Syntax oder das Verhalten von Ruby auf irgendeine Weise, und oft ist mehr als eine Art von Reflexion beteiligt. Nach der Einführung von Rubys Kern-Reflexions-API geht dieses Kapitel dazu über, anhand von Beispielen gängige Metaprogrammierungsverfahren zu demonstrieren, die diese API verwenden.
Beachten Sie, dass dieses Kapitel fortgeschrittene Themen behandelt. Sie können ein produktiver Ruby-Programmierer sein, ohne dieses Kapitel jemals gelesen zu haben. Sie könnten es hilfreich finden, zuerst die restlichen Kapitel dieses Buches zu lesen und dann zu diesem Kapitel zurückzukehren. Betrachten Sie dieses Kapitel als eine Art Abschlussprüfung: Wenn Sie die Beispiele verstehen (besonders die längeren am Ende), dann haben Sie Ruby gemeistert!
8.1 Typen, Klassen und Module
Die am häufigsten verwendeten reflektiven Methoden sind diejenigen, die verwendet werden, um den Typ eines Objekts zu bestimmen — welcher Klasse eine Instanz angehört und auf welche Methoden sie reagiert. Wir haben die meisten dieser wichtigen Methoden bereits am Anfang des Buches in „3.8.4 Objektklasse und Objekttyp“ vorgestellt. Zur Wiederholung:
o.class
Gibt die Klasse eines Objekts
o
zurück.
c.superclass
Gibt die übergeordnete Klasse einer Klasse
c
zurück.
o.instance_of? c
Ermittelt, ob
o.class == c
ist.
o.is_a? c
Ermittelt, ob
o
eine Instanz von
c
oder von einer ihrer Unterklassen ist. Wenn
c
ein Modul ist, dann testet diese Methode, ob
o.class
(oder einer ihrer Vorfahren) das Modul einbindet.
o.kind_of? c
kind_of?
ist ein Synonym für
is_a?
.
c === o
Bestimmt für jede Klasse oder jedes Modul
c
, ob
o.is_a?(c)
gilt.
o.respond_to? name
Ermittelt, ob das Objekt
o
eine Public- oder Protected-Methode mit dem angegebenen Namen besitzt. Wird
true
als zweites Argument übergeben, dann werden auch private Methoden geprüft.
8.1.1 Vorfahren und Module
Zusätzlich zu diesen Methoden, die Sie bereits gesehen haben, gibt es einige verwandte reflektive Methoden, um die Vorfahren einer Klasse oder eines Moduls zu ermitteln und herauszufinden, welche Module von einer Klasse oder einem Modul eingebunden werden. Diese Methoden sind einfach zu verstehen, wenn sie demonstriert werden:
module A; end # Leeres Modul
module B; include A; end;
Weitere Kostenlose Bücher