Thursday, May 17, 2007

Ruby, creating classes dynamically

Eine Klasse "Klass" mit einer Methode "meth" würde man ja normalerweise so definieren und instanzieren:

class Klass
def meth
"soso"
end
end

Klass.new.meth # => "soso"

Angenommen, man hätte den Inhalt der Klasse als String vorliegen, könnte man das Gleiche so machen:

s = <<eos
def meth()
"soso"
end
eos

Klass = Class.new() # neue leere Klasse erzeugen und der Konstante "Klass" zuweisen
Klass.class_eval s # "Evaluate" String (mit der Methodendefinition) im Kontext der Klasse

Klass.new.meth # => "soso"

Angenommen, man hätte auch den Namen, den die Klasse erhalten soll, als String vorliegen, so:

s = <<eos
def meth()
"soso"
end
eos

Kernel.const_set("Klass", Class.new())
Klass.class_eval s

Klass.new.meth # => "soso"

Angenommen, der Name, den die Klasse erhalten soll, wäre auch in dem String mit dem Inhalt der Klasse als Konstante definiert:

s = <<eos
NAME = 'Klass' # <= so soll die Klasse später mal heißen
def meth(); 'soso'; end
eos

c = Class.new
c.class_eval s
Kernel.const_set(c::NAME, c)

Klass.new.meth # => "soso"

Schon erstaunlich, oder?

No comments: