המודול Comparable
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 29 מתוך 57.
המודול המובנה Comparable של Ruby מעניק למחלקה את האופרטורים <, <=, ==, >, >= ואת המתודות between? ו־clamp. הוא זקוק למתודה אחת מהמחלקה: <=>, שמחזירה מספר שלילי, 0 או מספר חיובי כאשר האובייקט קטן יותר, שווה או גדול יותר:
class Weight
include Comparable
attr_reader :grams
def initialize(grams)
@grams = grams
end
def <=>(other)
grams <=> other.grams
end
end
a = Weight.new(500)
b = Weight.new(1200)
puts a < b
puts a == Weight.new(500)
puts b.between?(a, Weight.new(2000))פלט:
true
true
trueלמספרים ולמחרוזות כבר יש <=>, ולכן מחלקה בדרך כלל מאצילה את ההשוואה לאחד הערכים שלה. מערכים מושווים איבר אחר איבר, וכך ממיינים לפי כמה שדות בו־זמנית:
class Person
include Comparable
attr_reader :last, :first
def initialize(first, last)
@first = first
@last = last
end
def <=>(other)
[last, first] <=> [other.last, other.first]
end
end
a = Person.new("Ada", "Lovelace")
b = Person.new("Alan", "Turing")
c = Person.new("Byron", "Lovelace")
puts a < c
puts b > cפלט:
true
truesort, min ו-max משתמשות גם הן ב-<=>, ולכן אפשר למיין אובייקטים מהמחלקה בלי בלוק. clamp משאירה ערך בין שני ערכים אחרים:
class Weight
include Comparable
attr_reader :grams
def initialize(grams)
@grams = grams
end
def <=>(other)
grams <=> other.grams
end
def to_s
"#{grams}g"
end
end
list = [Weight.new(900), Weight.new(150), Weight.new(400)]
puts list.sort.join(", ")
puts list.max
puts Weight.new(5000).clamp(Weight.new(0), Weight.new(1000))פלט:
150g, 400g, 900g
900g
1000gהפעולה <=> אמורה להחזיר nil כשהאובייקט האחר אינו ניתן להשוואה. לאחר מכן Comparable מעלה ArgumentError עבור < ומחזירה false עבור ==, במקום להיכשל עם NoMethodError מבלבלת:
def <=>(other)
return nil unless other.is_a?(Weight)
grams <=> other.grams
end
Weight.new(1) == 5 # false
Weight.new(1) < 5 # ArgumentError: ההשוואה של Weight עם 5 נכשלהאתגר
קלהשלימו את המחלקה Weight. המתודה Weight.parse(text) קוראת ערכים כמו 500g, 1.2kg או 2lb (1 lb הוא 453.6 g) ושומרת את המשקל בגרמים. כללו את Comparable והגדירו את <=> לפי הגרמים. המתודה to_s מחזירה את מספר הגרמים מעוגל למספר שלם, כמו 1200g.
הקוד שסופק מנתח כל שורת קלט, ואז מדפיס את המשקלים ממוינים, את הכבד ביותר, את הקל ביותר, האם המשקל הראשון נמצא בין 1 kg ל־2 kg, ואת המשקל הראשון לאחר הגבלתו למקסימום של 1 kg.
הקוד שלכם צריך להופיע ב־weight.rb. הקובץ main.rb מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.
נסו בעצמכם
require_relative 'weight'
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input = []
while (line = gets)
input << line.chomp
end
weights = input.map { |line| Weight.parse(line) }
puts "sorted: #{weights.sort.join(", ")}"
puts "heaviest: #{weights.max}"
puts "lightest: #{weights.min}"
puts "first between 1kg and 2kg: #{weights[0].between?(Weight.parse("1kg"), Weight.parse("2kg"))}"
puts "first clamped: #{weights[0].clamp(Weight.parse("0g"), Weight.parse("1kg"))}"
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
3מתודות ומשתנים של מחלקה
מתודות של מחלקהמשתני מופע של מחלקהקבועיםמתודות ליצירת מופעיםסיכום – קודי קופון6מודולים ומיקסינים
מודולים ו-includeהרחבת אובייקטיםהמודול Comparableהמודול Enumerableסיכום - ליגת הספורטתרגלו בעצמכם: קומפיילר Ruby אונליין