Anonyme Klassen in Ruby

von Tobias Vetter
erstellt am 01. Juni 2023, zuletzt aktualisiert am 02. Juni 2023

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)) }