Menu
CoddyTech
flag Ar iconالعربيةdown icon

المجموعات المخصصة

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

يجمع صنف المجموعة عدة أساليب خاصة: each مع Enumerable، و<< للإضافة، وsize، وto_s وinspect للطباعة. يجب أن يعمل each أيضًا من دون كتلة، مع إرجاع مُعدِّد باستخدام to_enum، كما تفعل المصفوفات:

class TodoList
  include Enumerable

  def initialize
    @items = []
  end

  def <<(item)
    @items << item
    self
  end

  def each
    return to_enum(:each) unless block_given?

    @items.each { |item| yield item }
    self
  end
end

list = TodoList.new << "wash" << "shop" << "cook"
list.each.with_index(1) { |item, n| puts "#{n}. #{item}" }
p list.select { |i| i.include?("o") }

الناتج:

1. wash
2. shop
3. cook
["shop", "cook"]

تُخبر block_given? ما إذا كان المستدعي قد مرّر كتلة. والمُعدِّد الذي يتم إرجاعه من دون كتلة يدعم التسلسل مثل each.with_index أو each_slice أو next:

class Countdown
  include Enumerable

  def initialize(from)
    @from = from
  end

  def each
    return to_enum(:each) unless block_given?

    @from.downto(1) { |n| yield n }
  end
end

e = Countdown.new(3).each
puts e.next
puts e.next
p Countdown.new(5).each_slice(2).to_a

الناتج:

3
2
[[5, 4], [3, 2], [1]]

to_s هو النص الودّي للمستخدمين، بينما inspect هو ملخص قصير للمبرمجين. بالنسبة إلى مجموعة، يعرض inspect عادةً الصنف والحجم بدلًا من كل عنصر:

class TodoList
  include Enumerable

  def initialize(*items)
    @items = items
  end

  def each(&block)
    @items.each(&block)
  end

  def size
    @items.size
  end

  def to_s
    map.with_index(1) { |item, n| "#{n}. #{item}" }.join("\n")
  end

  def inspect
    "#<TodoList #{size} items>"
  end
end

list = TodoList.new("wash", "shop")
puts list
p list

الناتج:

1. wash
2. shop
#<TodoList 2 عناصر>

يوفّر Enumerable الدالة count، لكنه لا يوفّر size أو empty? أو << أو []: فهذه تنتمي إلى الصنف، لأنه وحده يعرف كيفية تخزين العناصر. ويجعل تعريفها المجموعة تبدو كمصفوفة بالنسبة إلى مستدعيها:

def size
  @items.size
end

def empty?
  @items.empty?
end

def [](index)
  @items[index]
end
challenge icon

التحدي

سهل

أكمل الصنف TodoList. يضيف << نص مهمة ويعيد القائمة. يمرّر each المهام ويعيد to_enum(:each) من دون كتلة. ضمّن Enumerable. يعيد size عدد المهام. يعيد to_s المهام في أسطر مرقمة، مثل 1. wash، أو nothing to do، ويعيد inspect القيمة #<TodoList 3 items>.

تضيف الشيفرة المزوّدة كل سطر من الإدخال من خلال التسلسل باستخدام <<، ثم تطبع القائمة، ونتيجة p للقائمة، والمهام مرقمة باستخدام ! عبر each.with_index(1) مثل 1! wash، وعدد المهام التي تحتوي على o، والمهمة الأولى أبجديًا.

ضع شيفرتك في todo_list.rb. يحتوي main.rb على شيفرة الإدخال/الإخراج المزوّدة ولا يمكن تعديلها.

جرّب بنفسك

require_relative 'todo_list'

# كود الإدخال/الإخراج المُزوَّد: اتركه كما هو
input = []
while (line = gets)
  input << line.chomp
end
list = input.reduce(TodoList.new) { |l, task| l << task }
puts list
p list
list.each.with_index(1) { |task, n| puts "#{n}! #{task}" }
puts "with o: #{list.count { |t| t.include?("o") }}"
puts "first: #{list.min}"
quiz iconاختبر نفسك

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

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

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