Gleichheit und Hash
Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 37 von 57.
Ruby kennt mehrere Arten von Gleichheit. == prüft die Wertgleichheit, die du für deine Klasse definierst. Hashes und uniq verwenden stattdessen zwei andere Methoden: eql? und hash. Wenn nur == definiert ist, sind gleiche Punkte weiterhin unterschiedliche Hash-Schlüssel:
class Point
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
def ==(other)
other.is_a?(Point) && x == other.x && y == other.y
end
end
a = Point.new(1, 2)
b = Point.new(1, 2)
puts a == b
puts [a, b].uniq.size
puts({ a => "first" }[b].inspect)Ausgabe:
true
2
nilEin Hash vergleicht zuerst hash-Werte, Zahlen, die aus einem Objekt berechnet werden, und prüft dann die Kandidaten mit eql?. Definiere beide anhand derselben Felder wie ==. alias eql? == verwendet == erneut, und [x, y].hash kombiniert die Felder:
class Point
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
def ==(other)
other.is_a?(Point) && x == other.x && y == other.y
end
alias eql? ==
def hash
[x, y].hash
end
end
a = Point.new(1, 2)
b = Point.new(1, 2)
puts [a, b, Point.new(3, 4)].uniq.size
puts({ a => "first" }[b])Ausgabe:
2
firstDie Regel lautet: Objekte, für die eql? gilt, müssen denselben hash haben. Zwei verschiedene Objekte können zufällig denselben Hash-Wert haben, weshalb eql? trotzdem prüft. Das Zählen mit einem Hash funktioniert dann mit Werten statt mit Identitäten:
class Word
attr_reader :text
def initialize(text)
@text = text.downcase
end
def ==(other)
other.is_a?(Word) && text == other.text
end
alias eql? ==
def hash
text.hash
end
end
counts = Hash.new(0)
%w[Ruby ruby RUBY gem].each { |t| counts[Word.new(t)] += 1 }
counts.each { |word, n| puts "#{word.text}: #{n}" }Ausgabe:
ruby: 3
gem: 1equal? bezeichnet weiterhin die Objektidentität und sollte niemals neu definiert werden. Eingebaute Werte befolgen diese Regeln bereits, weshalb Strings und Arrays als Hash-Schlüssel funktionieren:
a == b # gleicher Wert (du definierst ihn)
a.eql?(b) # gleicher Wert für Hash-Schlüssel und uniq (Alias von ==)
a.hash # eine Zahl; gleiche Objekte ergeben gleiche Zahlen
a.equal?(b) # dasselbe Objekt (niemals neu definieren)Aufgabe
EinfachVervollständige die Klasse Point, sodass Punkte mit denselben Koordinaten mit ==, eql? und hash gleich sind und als Hash-Schlüssel funktionieren. to_s gibt (1, 2) zurück.
Der bereitgestellte Code liest Punkte als Zeilen im Format x,y ein. Er gibt die Anzahl der unterschiedlichen Punkte mit uniq aus, zählt dann die Besuche pro Punkt in einem Hash und gibt sie in der Reihenfolge des ersten Besuchs als (1, 2): 2 aus und gibt schließlich aus, ob ein neues Point.new(0, 0) ein Schlüssel ist.
Dein Code gehört in point.rb. main.rb enthält den bereitgestellten Ein-/Ausgabecode und darf nicht bearbeitet werden.
Probier es selbst
require_relative 'point'
# Vorgegebener Ein-/Ausgabecode: unverändert lassen
input = []
while (line = gets)
input << line.chomp
end
points = input.map { |line| Point.new(*line.split(",").map(&:to_i)) }
puts "distinct: #{points.uniq.size}"
visits = Hash.new(0)
points.each { |pt| visits[pt] += 1 }
visits.each { |pt, n| puts "#{pt}: #{n}" }
puts "origin visited: #{visits.key?(Point.new(0, 0))}"
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Klassen und Objekte
Arbeiten mit DateienKlassen definierenInstanzvariablenMethoden und selfto_s und inspectRückblick – Bibliotheksausweis4Kapselung
Private MethodenGeschützte MethodenPrivate SetterZustand schützenRückblick – Verkaufsautomat7Polymorphismus und Duck Typing
PolymorphismusDuck TypingAbstrakte MethodenFälle und KlassenRückblick – Zahlungsmethoden2Getter und Setter sowie self
Leser und SchreiberBenutzerdefinierte Setterself in MethodenIdentität und GleichheitWiederholung – Kontaktliste5Vererbung
UnterklassenMethoden überschreibensuper aufrufenis_a? und VorfahrenRückblick – Gehaltsabrechnung des Personals8Spezielle Methoden
Gleichheit und HashOperator-MethodenIndexieren und AnhängenBenutzerdefinierte CollectionsRückblick – Brüche11Projekt: Bibliotheksverwaltung
Bücher und MitgliederBücher ausleihenÜbe selbstständig: Online-Ruby-Compiler