Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الحالات والفئات

جزء من قسم البرمجة كائنية التوجه في رحلة Ruby على Coddy. الدرس 35 من 57.

يمكن لـ case التفرّع اعتمادًا على فئة قيمة ما. يطابق when Integer كل عدد صحيح، لأن case يقارن باستخدام ===، وInteger === 5 يسأل عمّا إذا كان 5 من نوع Integer (is_a?):

def describe(value)
  case value
  when Integer then "integer #{value}"
  when Float then format("float %.2f", value)
  when String then "text of #{value.size} chars"
  when nil then "nothing"
  else "other: #{value.class}"
  end
end

[5, 2.5, "hi", nil, [1, 2]].each { |v| puts describe(v) }

الناتج:

integer 5
float 2.50
text of 2 chars
nothing
other: Array

لأن === في الصنف يتبع is_a?، فإن when الذي يحتوي على صنف فائق يطابق أصنافه الفرعية أيضًا. رتّب الفروع من الصنف الأكثر تخصيصًا إلى الأكثر عمومية:

class Animal
end

class Dog < Animal
end

def kind(x)
  case x
  when Dog then "a dog"
  when Animal then "some animal"
  else "not an animal"
  end
end

puts kind(Dog.new)
puts kind(Animal.new)
puts kind("Rex")
puts Animal === Dog.new

الناتج:

a dog
some animal
not an animal
true

يمكن لكتلة when واحدة أن تسرد عدة أصناف، ويمكن للفروع تنفيذ عمل فعلي باستخدام القيمة، مثل حساب مجموع بنية متداخلة من أنواع مختلطة:

def total(value)
  case value
  when Integer, Float then value
  when String then value.to_f
  when Array then value.sum { |v| total(v) }
  when Hash then total(value.values)
  else 0
  end
end

puts total([1, "2.5", { a: 3, b: [4, nil] }])

الناتج:

10.5

التفرّع حسب الفئات يناسب القيم التي لا يمكنك منح فئاتها أساليب جديدة، مثل الأعداد والسلاسل والمصفوفات، أو البيانات الواردة من الخارج. أما بالنسبة إلى فئاتك الخاصة، ففضّل تعدد الأشكال: إذ تحتاج الفئة الجديدة حينها إلى أسلوب جديد، لا إلى فرع جديد في كل case:

# فئاتك الخاصة: دع كل واحدة يجيب
shape.area

# القيم المدمجة من الخارج: تفرع حسب الفئة
case value
when Integer then ...
when String then ...
end
challenge icon

التحدي

سهل

أكمل الدالة المساعدة describe(value) في functions.rb باستخدام case على فئة القيمة. تُرجع integer 5 (odd) أو integer 4 (even)، وfloat 2.50 بمنزلتين عشريتين، وtext "hi" (2 chars)، وlist of 3: 1, a, 2.5 (مع ضمّ العناصر بعد تحويلها باستخدام to_s)، وnothing للقيمة nil، وother Symbol لأي قيمة أخرى. الرموز هي النوع الآخر الوحيد الموجود في الاختبارات.

يحوّل الكود المُ supplied كل سطر إدخال إلى قيمة (أعداد صحيحة، وكسور عشرية، وقوائم [a,b]، وnil، ورموز :name، أو نص) ويطبع describe لكل قيمة.

ضع الكود الخاص بك في functions.rb. يحتوي main.rb على كود الإدخال/الإخراج المُ supplied ولا يمكن تعديله.

جرّب بنفسك

require_relative 'functions'

# كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
input = []
while (line = gets)
  input << line.chomp
end
def parse(text)
  return Integer(text) if text.match?(/\A-?\d+\z/)
  return Float(text) if text.match?(/\A-?\d+\.\d+\z/)
  return nil if text == "nil"
  return text[1..].to_sym if text.start_with?(":")
  return text[1...-1].split(",").map { |t| parse(t) } if text.start_with?("[")

  text
end

input.each { |line| puts describe(parse(line)) }
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Ruby عبر الإنترنت