وحدة 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"))}"
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتمتغيرات النسخةالأساليب و selfto_s و inspectمراجعة - بطاقة المكتبة7تعدد الأشكال والكتابة بأسلوب البطة
تعدد الأشكالالكتابة بأسلوب البطةالأساليب المجردةالحالات والفئاتمراجعة - طرق الدفع3أساليب ومتغيرات الأصناف
أساليب الأصنافمتغيرات كائنات الأصنافالثوابتأساليب الإنشاءمراجعة - رموز القسائمتدرّب بنفسك: مترجم Ruby عبر الإنترنت