שוויון ו-hash
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 37 מתוך 57.
ל-Ruby יש כמה סוגים של שוויון. == בודק שוויון ערכים, שאותו מגדירים עבור המחלקה שלך. גיבובים ו-uniq משתמשים בשתי שיטות אחרות במקום זאת: eql? ו-hash. כאשר מגדירים רק את ==, נקודות שוות עדיין נחשבות למפתחות גיבוב שונים:
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)פלט:
true
2
nilHash משווה תחילה ערכי hash, מספרים המחושבים מתוך אובייקט, ואז בודק מועמדים באמצעות eql?. הגדירו את שניהם לפי אותם שדות כמו ==. alias eql? == עושה שימוש חוזר ב-==, ו-[x, y].hash משלב את השדות:
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])פלט:
2
firstהכלל הוא: לאובייקטים שעבורם eql? מחזירה true חייב להיות אותו ערך של hash. ייתכן שלשני אובייקטים שונים יהיה במקרה אותו ערך hash, וזו הסיבה שהבדיקה eql? עדיין נחוצה. לכן, ספירה באמצעות Hash פועלת על ערכים במקום על זהויות:
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}" }פלט:
ruby: 3
gem: 1equal? נשארת זהות, ואסור להגדיר אותה מחדש. ערכים מובנים כבר פועלים לפי הכללים האלה, ולכן מחרוזות ומערכים יכולים לשמש כמפתחות של Hash:
a == b # אותו ערך (אתם מגדירים זאת)
a.eql?(b) # אותו ערך עבור מפתחות Hash ו-uniq (כינוי של ==)
a.hash # מספר; אובייקטים שווים מחזירים מספרים שווים
a.equal?(b) # אותו אובייקט (לעולם אין להגדיר מחדש)אתגר
קלהשלימו את המחלקה Point כך שנקודות עם אותן קואורדינטות יהיו שוות באמצעות ==, eql? ו-hash, ויוכלו לשמש כמפתחות ב-Hash. to_s מחזירה (1, 2).
הקוד שסופק קורא נקודות משורות בפורמט x,y. הוא מדפיס את מספר הנקודות הייחודיות באמצעות uniq, ואז סופר את הביקורים בכל נקודה ב-Hash ומדפיס אותם לפי סדר הביקור הראשון בתור (1, 2): 2, ולבסוף מציין אם Point.new(0, 0) חדשה היא מפתח.
הקוד שלך צריך להופיע בקובץ point.rb. הקובץ main.rb מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.
נסו בעצמכם
require_relative 'point'
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
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))}"
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
3מתודות ומשתנים של מחלקה
מתודות של מחלקהמשתני מופע של מחלקהקבועיםמתודות ליצירת מופעיםסיכום – קודי קופוןתרגלו בעצמכם: קומפיילר Ruby אונליין