Die Programmiersprache Ruby (German Edition)
verwenden, um Instanzvariablen dieses Objekts zu lesen und zu setzen. Wir könnten das wie folgt erledigen:
class Object # Object öffnen, um eine neue Methode einzufügen
def bindings # Plural bei dieser Methode beachten
binding # Dies ist die vordefinierte Kernel-Methode.
end
end
class Test # Einfache Klasse mit einer Instanzvariablen
def initialize(x); @x = x; end
end
t = Test.new(10) # Ein Test-Objekt erzeugen
eval("@x", t.bindings) # => 10: Wir haben in t hineingespäht.
Beachten Sie, dass es eigentlich nicht notwendig ist, eine
Object.bindings
-Methode dieser Art zu definieren, um die Instanzvariablen eines Objekts auszuspähen. Diverse andere Methoden, die in Kürze beschrieben werden, bieten einfachere Möglichkeiten, den Wert der Instanzvariablen eines Objekts auszulesen (und zu setzen).
Wie in „6.6.2 Closures und Bindungen“ beschrieben, definiert das
Proc
-Objekt eine öffentliche
binding
-Methode, die ein
Binding
-Objekt zurückgibt; es stellt die für den Rumpf dieser
Proc
wirksamen Variablenbindungen dar. Weiterhin erlaubt die Methode
eval
es Ihnen, ein
Proc
-Objekt statt eines
Binding
-Objekts als zweites Argument zu übergeben.
Ruby 1.9 definiert eine
eval
-Methode für
Binding
-Objekte; anstatt also eine
Binding
als zweites Argument des globalen
eval
zu übergeben, können Sie die Methode
eval
einer
Binding
aufrufen. Welche Variante Sie wählen, ist bloß eine Frage des Stils; beide Verfahren sind äquivalent.
8.2.2 instance_eval und class_eval
Die Klasse
Object
definiert eine Methode namens
instance_eval
, und die Klasse
Module
definiert eine Methode namens
class_eval
. (
module_eval
ist ein Synonym für
class_eval
.) Beide Methoden werten Ruby-Code aus, genau wie
eval
, aber es gibt zwei wichtige Unterschiede. Der erste ist, dass sie den Code im Kontext des angegebenen Objekts beziehungsweise im Kontext des angegebenen Moduls auswerten – das Objekt oder Modul ist der Wert von
self
, während der Code ausgewertet wird. Hier einige Beispiele:
o.instance_eval("@x") # Wert der o-Instanzvariablen @x zurückgeben
# Instanzmethode len für String definieren, um String-Länge zurückzugeben
String.class_eval("def len; size; end")
# Hier eine andere Möglichkeit, dies zu tun
# Der Code verhält sich, als stünde er zwischen "class String" und "end".
String.class_eval("alias len size")
# instance_eval verwenden, um Klassenmethode String.empty zu definieren
# Achtung: Verschachtelte Anführungszeichen sind etwas verzwickt ...
String.instance_eval(""def empty; ''; end"")
Beachten Sie den kleinen, aber wichtigen Unterschied zwischen
instance_eval
und
class_eval
, wenn der ausgewertete Code eine Methodendefinition enthält.
instance_eval
definiert Singleton-Methoden des Objekts (und dies ergibt Klassenmethoden, wenn die Methode für ein Klassenobjekt aufgerufen wird).
class_eval
definiert reguläre Instanzmethoden.
Der zweite wichtige Unterschied zwischen diesen beiden Methoden und dem globalen
eval
ist, dass
instance_eval
und
class_eval
einen Codeblock zur Auswertung annehmen können. Wenn ein Block statt eines String übergeben wird, dann wird der Code innerhalb des Blocks im entsprechenden Kontext ausgeführt. Hier sehen Sie deshalb Alternativen zu den oben gezeigten Aufrufen:
o.instance_eval { @x }
String.class_eval {
def len
size
end
}
String.class_eval { alias len size }
String.instance_eval { def empty; ""; end }
8.2.3 instance_exec und class_exec
Ruby 1.9 definiert zwei weitere Auswertungsmethoden:
instance_exec
und
class_exec
(und ihr Alias
module_exec
). Diese Methoden werten einen Block (aber keinen String) mit Code im Kontext des Empfängerobjekts aus, genau wie
instance_eval
und
class_eval
. Der Unterschied besteht darin, dass die
exec
-Methoden Argumente akzeptieren und diese an den Block übergeben. Auf diese Weise wird der Codeblock im Kontext des angegebenen Objekts ausgewertet, aber mit Parametern, deren Werte von außerhalb des Objekts stammen.
8.3 Variablen und Konstanten
Kernel
,
Object
und
Module
definieren reflektive Methoden, um die Namen (als Strings) aller definierten globalen Variablen, zurzeit definierten lokalen Variablen, aller Instanzvariablen eines Objekts, aller Klassenvariablen einer Klasse oder eines Moduls sowie alle Konstanten einer Klasse oder eines Moduls aufzulisten:
global_variables # => ["$DEBUG", "$SAFE", ...]
x = 1 # Eine lokale Variable definieren
local_variables # => ["x"]
# Eine einfache Klasse definieren
class Point
def initialize(x,y);
Weitere Kostenlose Bücher