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. Hashy i uniq używają zamiast tego dwóch innych metod: eql? i hash. Gdy zdefiniowane jest tylko ==, równe punkty nadal są różnymi kluczami hashy:
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
firstZasada jest taka: obiekty, które są eql?, muszą mieć ten sam hash. Dwa różne obiekty mogą przypadkowo mieć tę samą wartość skrótu, dlatego eql? nadal sprawdza równość. Wtedy zliczanie za pomocą Hash działa na wartościach, a nie 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 sprawdza tożsamość i nigdy nie należy go redefiniować. Wbudowane wartości już przestrzegają tych reguł, dlatego łańcuchy i tablice mogą być kluczami Hash:
a == b # ta sama wartość (definiujesz ją samodzielnie)
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, tak aby punkty o tych samych współrzędnych były równe za pomocą ==, eql? i hash oraz działały jako klucze Hash. to_s zwraca (1, 2).
Dostarczony kod odczytuje punkty z wierszy w formacie x,y. Wypisuje liczbę różnych punktów za pomocą uniq, następnie zlicza odwiedziny każdego punktu w Hash 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.
Twój kod umieść w pliku point.rb. 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