Menu
Coddy logo textTech
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 عبر الإنترنت