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:
"Point-ähnliches Argument erwartet" unless
    other.respond_to? :x and other.respond_to? :y
Point.new(@x + other.x, @y + other.y)
end
    Beachten Sie, dass diese Version der Methode immer noch davon ausgeht, dass die Methoden
x
und
y
Zahlen zurückgeben. Wir würden einen unverständlichen Fehler erhalten, wenn eine der Methoden zum Beispiel einen String liefert.
    Ein anderer Ansatz bei der Typprüfung setzt nach dem Einsatz der Methode an. Wir können einfach jede Exception abfangen, die während der Ausführung der Methode auftritt, und eine passendere eigene Exception werfen:
def +(other) # Annahme, dass other wie ein Punkt aussieht
Point.new(@x + other.x, @y + other.y)
rescue # Wenn etwas schiefgeht,
raise TypeError, # unsere eigene Exception werfen
    "Point-Addition mit einem Argument, das nicht wie ein Point quakt!"
end
    ----
# Wenn wir versuchen, der Methode * von Integer einen Point zu übergeben, ruft
# Integer diese Methode von Point auf und versucht dann, die Elemente des Array
# zu multiplizieren. Anstatt hier eine Typumwandlung vorzunehmen, vertauschen
# wir die Reihenfolge der Operanden, so dass wir die oben definierte Methode *
# aufrufen.
def coerce(other)
[self, other]
end
    7.1.7 Array- und Hash-Zugriff mit []
    Ruby nutzt eckige Klammern für den Array- und Hash-Zugriff und ermöglicht beliebigen Klassen, eine Methode
[]
zu definieren, um diese Klammern damit selber zu verwenden. Lassen Sie uns eine Methode
[]
für unsere Klasse definieren, um es
Point
-Objekten zu ermöglichen, als nur lesbare Arrays der Länge
2
oder als nur lesbare Hashes mit den Schlüsseln
:x
und
:y
behandelt zu werden:
# Definiere Methode [], um einen Point wie ein Array oder
# einen Hash mit den Schlüsseln :x und :y zu behandeln
def [](index)
case index
when 0, −2: @x # Index 0 (oder −2) ist die x-Koordinate.
when 1, −1: @y # Index 1 (oder −1) ist die y-Koordinate.
when :x, "x": @x # Hash-Schlüssel als Symbol oder String für x
when :y, "y": @y # Hash-Schlüssel als Symbol oder String für y
else nil # Arrays und Hashes liefern nur nil zurück, wenn das
     # Element nicht vorhanden ist.
end
end
    7.1.8 Koordinaten enumerieren
    Wenn sich ein
Point
-Objekt wie ein Array mit zwei Elementen verhalten kann, sollten wir vielleicht auch in der Lage sein, über diese Elemente so zu iterieren, wie wir es bei einem echten Array können. Das folgende Codebeispiel zeigt die Definition des
each
-Iterators für unsere Klasse
Point
. Da ein
Point
immer genau zwei Elemente besitzt, muss unser Iterator nicht durch eine Schleife laufen — es reicht einfach, zweimal
yield
aufzurufen:
# Dieser Iterator übergibt dem entsprechenden Block die x-Koordinate, dann
# die y-Koordinate und springt dann zurück. So können wir einen Punkt so
# enumerieren, als ob es sich um ein Array aus zwei Elementen handelt. Diese
# Methode each ist für das # Modul Enumerable notwendig.
def each
yield @x
yield @y
end
    Mit einem auf diese Weise definierten Iterator können wir Code wie den folgenden schreiben:
p = Point.new(1,2)
p.each {|x| print x } # Gibt "12" aus
    Wichtiger ist noch, dass wir durch die Definition des Iterators
each
die Methoden aus dem Modul
Enumerable
hineinmischen können, die alle per
each
definiert sind. Unsere Klasse ermöglicht über 20 zusätzliche Iteratoren nur durch das Hinzufügen einer einzelnen Zeile:
include Enumerable
    Wenn wir das tun, können wir sehr interessanten Code schreiben, zum Beispiel:
# Befindet sich der Punkt P im Ursprung?
p.all? {|x| x == 0 } # True, wenn der Block für alle Elemente true zurückgibt
    7.1.9 Point und Gleichheit
    So wie unsere Klasse momentan definiert ist, sind zwei verschiedene Instanzen von
Point
niemals gleich, selbst wenn ihre x- und y-Koordinaten dieselben sind. Um das zu ändern, müssen wir eine Implementierung des Operators
==
bereitstellen. (Eventuell sollten Sie nochmals „3.8.5 Objektgleichheit“ in Kapitel 3 lesen, um sich Rubys verschiedene Formen von Gleichheit ins Gedächtnis zu rufen.)
    Hier eine Methode
==
für
Point
:
def ==(o) # Ist self == o?
if o.is_a? Point # Wenn o ein Point-Objekt ist,
    @x==o.x && @y==o.y # vergleiche die Felder.
else # Wenn o kein Point ist,
    false # ist per Definition self != o.
end
end
    Rufen Sie sich aus „3.8.5 Objektgleichheit“ in Erinnerung, dass Objekte in Ruby auch eine Methode
eql?
für das Testen auf Gleichheit bieten. Standardmäßig prüft die Methode
eql?
wie der Operator
==
die Identität von Objekten und nicht die

Weitere Kostenlose Bücher