Równość i hash
Część sekcji Programowanie obiektowe ścieżki Ruby w Coddy. Lekcja 37 z 57.
Ruby ma kilka rodzajów równości. == oznacza równość wartości, którą definiujesz dla swojej klasy. Skróty i uniq używają zamiast tego dwóch innych metod: eql? i hash. Gdy zdefiniowano tylko ==, równe punkty nadal są różnymi kluczami skrótu:
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)Wynik:
true
2
nilHash najpierw porównuje wartości hash, czyli liczby obliczone na podstawie obiektu, a następnie sprawdza kandydatów za pomocą eql?. Zdefiniuj obie metody na podstawie tych samych pól co ==. alias eql? == ponownie wykorzystuje ==, a [x, y].hash łączy pola:
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])Wynik:
2
firstReguła jest następująca: obiekty, dla których eql? zwraca prawdę, muszą mieć tę samą wartość hash. Dwa różne obiekty mogą przypadkowo mieć tę samą wartość skrótu, dlatego eql? nadal sprawdza ich równość. Dzięki temu zliczanie za pomocą Hash działa na wartościach zamiast na tożsamości obiektów:
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}" }Wynik:
ruby: 3
gem: 1equal? nadal oznacza tożsamość i nigdy nie należy go redefiniować. Wartości wbudowane już przestrzegają tych zasad, dlatego ciągi znaków i tablice działają jako klucze hasza:
a == b # ta sama wartość (sam ją definiujesz)
a.eql?(b) # ta sama wartość dla kluczy Hash i uniq (alias ==)
a.hash # liczba; równe obiekty dają równe liczby
a.equal?(b) # ten sam obiekt (nigdy nie redefiniuj)Wyzwanie
ŁatwyUzupełnij klasę Point, aby punkty o tych samych współrzędnych były równe przy użyciu ==, eql? i hash oraz mogły być kluczami Hasha. to_s zwraca (1, 2).
Dostarczony kod odczytuje punkty z wierszy w formacie x,y. Wypisuje liczbę różnych punktów za pomocą uniq, a następnie zlicza odwiedziny każdego punktu w Hashu i wypisuje je w kolejności pierwszych odwiedzin jako (1, 2): 2, a na końcu informuje, czy nowy Point.new(0, 0) jest kluczem.
Umieść swój kod w pliku point.rb. Plik main.rb zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
require_relative 'point'
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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))}"
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Klasy i obiekty
Praca z plikamiDefiniowanie klasZmienne instancjiMetody i selfto_s i inspectPowtórzenie – karta biblioteczna4Hermetyzacja
Metody prywatneMetody chronionePrywatne setteryOchrona stanuPowtórzenie – automat vendingowy7Polimorfizm i typowanie kacze
PolimorfizmTypowanie kaczeMetody abstrakcyjnecase i klasyPowtórzenie – metody płatności10Wzorce projektowe, część 2
Delegowanie z ForwardableWzorzec dekoratoraWzorzec budowniczegoWzorzec stanu2Metody dostępowe i self
Gettery i setteryWłasne setteryself w metodachTożsamość i równośćPowtórzenie – lista kontaktów5Dziedziczenie
PodklasyNadpisywanie metodWywoływanie superis_a? i przodkowiePowtórka – lista płac pracowników8Metody specjalne
Równość i hashMetody operatorówIndeksowanie i dodawanieWłasne kolekcjePowtórka – ułamki11Projekt: Zarządzanie biblioteką
Książki i czytelnicyWypożyczanie książekPoćwicz samodzielnie: Kompilator Ruby online