Bücher online kostenlos Kostenlos Online Lesen
Die Programmiersprache Ruby (German Edition)

Die Programmiersprache Ruby (German Edition)

Titel: Die Programmiersprache Ruby (German Edition) Kostenlos Bücher Online Lesen
Autoren: David Flanagan , Yukihiro Matsumoto
Vom Netzwerk:
Gleichheit der Objektinhalte. Häufig möchten wir, dass
eql?
genauso funktioniert wie der Operator
==
, was wir durch einen Alias erreichen:
class Point
alias eql? ==
end
    Andererseits gibt es zwei Gründe, warum sich
eql?
von
==
unterscheiden sollte. Erstens definieren manche Klassen
eql?
, um einen strengeren Vergleich als
==
durchzuführen. In
Numeric
und seinen Subklassen ermöglicht zum Beispiel
==
eine Typkonvertierung, während das bei
eql?
nicht der Fall ist. Wenn wir denken, dass die Anwender unserer Klasse
Point
die Instanzen eventuell auf unterschiedliche Arten vergleichen wollen, sollten wir diesen Weg einschlagen. Da Punkte nur zwei Zahlen sind, wäre es sinnvoll, sich hier an
Numeric
zu orientieren. Unsere Methode
eql?
würde der Methode
==
sehr ähnlich sehen, aber
eql?
statt
==
verwenden, um die Punktkoordinaten zu vergleichen:
def eql?(o)
if o.instance_of? Point
    @x.eql?(o.x) && @y.eql?(o.y)
elsif
    false
end
end
    ----
    Duck Typing und Gleichheit
    Der Operator
+
, den wir weiter oben definiert haben, nimmt keinerlei Typprüfung vor – er funktioniert mit jeglichem Objekt als Argument, dessen Methode
x
und
y
Zahlen zurückgibt. Diese Methode
==
ist anders implementiert: Anstatt Duck Typing zu ermöglichen, ist es erforderlich, dass es sich beim Argument um einen
Point
handelt. Das Ganze ist eine Frage der Implementierung. Bei der obigen Implementierung von
==
hat man sich dafür entschieden, Gleichheit so zu definieren, dass ein Objekt nur dann einem
Point
entsprechen kann, wenn es selber ein
Point
ist.
    Man kann Implementierungen strikter oder laxer gestalten. Die hier genutzte Implementierung hat das Prädikat
is_a?
verwendet, um die Klasse des Arguments zu prüfen. Damit kann eine Instanz einer Subklasse von
Point
gleich einem
Point
sein. Eine striktere Implementierung würde
instance_of?
nutzen, um keine Instanzen von Subklassen zuzulassen. Auch nutzt die Implementierung
==
, um die x- und y-Koordinaten zu vergleichen. Bei Zahlen erlaubt der Operator
==
eine Typkonvertierung, womit der Punkt
(1,1)
gleich dem Punkt
(1.0,1.0)
wäre. Das ist vermutlich das, was man möchte, aber eine striktere Defnition der Gleichheit könnte
eql?
verwenden, um die Koordinaten zu vergleichen.
    Eine laxere Definition der Gleichheit würde Duck Typing unterstützen. Man muss dabei aber vorsichtig sein. Unsere Methode
==
sollte zu keinem
NoMethodError
führen, wenn das Argumentobjekt keine Methoden
x
und
y
besitzt. Stattdessen sollte es einfach
false
zurückgeben:
def ==(o) # Ist self == o?
@x == o.x && @y == o.y # Annahme: o hat passende Methoden x und y
rescue # Wenn das nicht stimmt,
false # gilt self != o
end
    ----
    Es sei hier angemerkt, dass dies die richtige Vorgehensweise für alle Klassen ist, die Collections (Sets, Listen, Bäume) beliebiger Objekte implementieren. Der Operator
==
sollte die Elemente der Collection mithilfe ihrer
==
-Operatoren vergleichen, während die Methode
eql?
das mit den
eql?
-Methoden der Elemente macht.
    Der zweite Grund, eine Methode
eql?
zu implementieren, die sich vom Operator
==
unterscheidet, ist, wenn Sie Instanzen Ihrer Klasse bei der Verwendung als Hash-Schlüssel ein besonderes Verhalten angedeihen lassen wollen. Die Klasse
Hash
nutzt
eql?
, um Hash-Schlüssel zu vergleichen (allerdings nicht Werte). Wenn Sie
eql?
undefiniert lassen, werden die Hashes Instanzen Ihrer Klasse anhand der Objektidentität vergleichen. Wenn Sie also einen Wert mit einem Schlüssel
p
verbinden, werden Sie diesen Wert nur mit genau dem entsprechenden Objekt
p
auslesen können. Ein Objekt
q
wird nicht funktionieren, selbst wenn gilt:
p == q
. Veränderbare Objekte lassen sich nicht gut als Hash-Schlüssel nutzen, aber wenn Sie
eql?
undefiniert lassen, umgehen Sie dieses Problem geschickt. (Siehe „3.4.2 Hash-Codes, Gleichheit und veränderliche Schlüssel“ , wenn Sie mehr zu Hashes und veränderlichen Schlüsseln erfahren wollen.)
    Da
eql?
für Hashes verwendet wird, dürfen Sie diese Methode niemals allein implementieren. Wenn Sie eine Methode
eql?
definieren, müssen Sie auch eine Methode
hash
schreiben, um einen Hashcode für Ihr Objekt zu berechnen. Wenn zwei Objekte laut
eql?
gleich sind, müssen ihre
hash
-Methoden denselben Wert zurückgeben. (Zwei nicht gleiche Objekte können eventuell den gleichen Hashcode besitzen, aber Sie sollten das soweit wie möglich vermeiden.)
    Das Implementieren optimaler
hash
-Methoden kann sehr schwierig sein. Glücklicherweise gibt es einen einfachen

Weitere Kostenlose Bücher