המודול 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
trueגם sort, 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 אונליין