Die Programmiersprache Ruby (German Edition)
ausdrückt, dass Kopien nicht erlaubt sind. Solch eine Fehlermeldung kann für Programmierer, die Ihre Klasse nutzen, sehr hilfreich sein.
7.4.4 marshal_dump und marshal_load
Eine dritte Möglichkeit, Objekte zu erstellen, ergibt sich, wenn
Marshal.load
aufgerufen wird, um Objekte neu zu erstellen, die vorher mit
Marshal.dump
gemarshallt (oder »serialisiert«) wurden.
Marshal.dump
speichert die Klasse eines Objekts und marshallt rekursiv den Wert jeder seiner Instanzvariablen. Das funktioniert gut — die meisten Objekte können mit diesen beiden Methoden gesichert und wieder geladen werden.
Manche Klassen müssen die Art und Weise, wie das Marshalling (und Unmarshalling) durchgeführt wird, ändern. Ein Grund dafür kann sein, eine kompaktere Darstellung eines Objektzustands zu erreichen. Ein anderer Grund ist, das Speichern von kurzlebigen Daten zu vermeiden, wie zum Beispiel den Inhalt eines Cache, der sowieso geleert werden müsste, wenn das Objekt geunmarshallt wird. Sie können die Art, wie ein Objekt gemarshallt wird, anpassen, indem Sie eine Instanzmethode
marshal_dump
in der Klasse definieren – sie sollte ein anderes Objekt zurückgeben (zum Beispiel einen String oder ein Array mit den Werten von ausgewählten Instanzvariablen), das dann anstelle des eigentlichen Objekts gemarshallt wird.
Wenn Sie eine eigene Methode
marshal_dump
definieren, müssen Sie natürlich auch eine passende Methode
marshal_load
angeben.
marshal_load
wird für eine neu allozierte (mit
allocate
), aber nicht initialisierte Instanz der Klasse aufgerufen. Ihr wird eine rekonstruierte Kopie des Objekts übergeben, das von
marshal_dump
zurückgeliefert wurde, und sie muss den Zustand des Empfängerobjekts basierend auf dem Zustand des übergebenen Objekts initialisieren.
Lassen Sie uns als Beispiel zur multidimensionalen
Point
-Klasse zurückkehren, mit der wir weiter oben begonnen hatten. Wenn wir die Einschränkung haben, dass alle Koordinaten Ganzzahlen sein müssen, können wir ein paar Bytes im gemarshallten Objekt sparen, indem wir das Array mit Integer-Koordinaten in einen String packen (Sie können mit ri mehr über
Array.pack
erfahren, um diesen Code besser zu verstehen):
class Point # Ein Punkt im n-dimensionalen Raum
def initialize(*coords) # Beliebige Anzahl von Koordinaten übernehmen
@coords = coords # Koordinaten in einem Array speichern
end
def marshal_dump # Koordinaten in einen String packen und diesen marshallen
@coords.pack("w*")
end
def marshal_load(s) # Koordinaten aus dem geunmarshallten String entpacken
@coords = s.unpack("w*") # und mit ihnen das Objekt initialisieren
end
end
Wenn Sie eine Klasse schreiben — wie die Klasse
Season
weiter oben — , für die Sie die Methoden
clone
und
dup
deaktiviert haben, müssen Sie auch eigene Marshalling-Methoden implementieren, da das Dumpen und Laden eines Objekts eine einfache Möglichkeit bietet, eine Kopie davon zu erzeugen. Sie können das Marshalling komplett unterbinden, indem Sie die Methoden
marshal_dump
und
marshal_load
so definieren, dass sie eine Exception werfen, aber das ist schon eine recht harsche Vorgehensweise. Eleganter ist es, das Unmarshalling so anzupassen, dass
Marshal.load
ein bestehendes Objekt statt einer Kopie zurückliefert.
Dazu müssen wir einen anderen Satz von eigenen Marshalling-Methoden definieren, da der Rückgabewert von
marshal_load
ignoriert wird.
_dump
ist eine Instanzmethode, die den Zustand des Objekts als String zurückgeben muss. Die dazugehörige Methode
_load
ist eine Klassenmethode, die den von
_dump
zurückgegebenen String erwartet und ein Objekt liefert.
_load
darf ein neues Objekt erzeugen oder eine Referenz auf ein bestehendes Objekt zurückgeben.
Um Marshalling zu erlauben, das Kopieren von
Season
-Objekten aber zu unterbinden, fügen wir der Klasse diese Methoden hinzu:
class Season
# Wir wollen Season-Objekte marshallen können, aber keine neuen
# Instanzen erzeugen lassen, wenn sie geunmarshallt werden.
def _dump(limit) # Eigene Marshalling-Methode
@n.to_s # Liefert Index als String zurück
end
def self._load(s) # Eigene Unmarshalling-Methode
INSTANCES[Integer(s)] # Liefert bestehende Instanz zurück
end
end
7.4.5 Das Singleton-Muster
Ein Singleton ist eine Klasse, die nur eine einzige Instanz hat. Singletons können genutzt werden, um globale Programmzustände in einem objektorientierten Framework zu speichern, und sie können nützliche Alternativen zu Klassenmethoden und Klassenvariablen
Weitere Kostenlose Bücher