Anonyme Klassen in Ruby
Anonyme Klassen in Ruby erlauben es, eine Klasse zu initialisieren, ohne diese automatisch als einer Konstante im globalen Namensraum zuzuweisen. Dies ist besonders nützlich, wenn man Tests für Mixins schreibt oder private Hilfsklassen innerhalb einer anderen Klasse verwenden möchte. Möchte man etwa eine kleine Klasse zur Kapselung von Koordinaten eines Punktes implementieren, kann man dies entweder auf dem normalen, globalen Weg tun:
class Point
attr_accessor :x, :y
end
Oder auf dem anonymen Weg: Class.new { attr_accessor :x, :y }
In beiden Fällen kann das Objekt erst initialisiert und dann befüllt werden. Aber der anonyme Weg erlaubt eine einmalige, sofortige Initialisierung:
point = Class.new { attr_accessor :x, :y }.new
point.x = 1
point.y = 2
Dies kann besonders praktisch für die Übergabe komplexer Parameter an andere Objekte sein. Dies wird zwar auch durch ein OpenStruct möglich, welches aber erheblich langsamer ist.
Möchte man beispielsweise die Implementation des bekannte Pattern Callable testen, kann dies folgendermaßen geschehen. Gegeben dem Modul:
module Callable
def call(*args)
new(*args).call
end
end
Im Kontext von Unit-Tests ermöglicht dies statt eine andere Klasse oder Modul in den Unit-Test hineinzuziehen (und damit die Grenzen des Unit-Tests zu verletzten) stattdessen eine anonyme Klasse initialisieren, die diesen Mixin verwendet. Dieses kann auch als Blaupause für die Verwendbarkeit des Mixins dienen. Ein Beispiel in RSpec:
let(:klass) { Class.new do
extend Callable
def initialize(x, y)
@x = x
@y = y
end
def call = [@x, @y]
end
}
it { expect(klass.new(1, 2).call).to eq klass.call(1, 2)) }