Menu
Coddy logo textTech

אוספים מותאמים אישית

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 40 מתוך 57.

מחלקת אוסף משלבת כמה מתודות מיוחדות: each עם Enumerable, << להוספה, size, ו-to_s ו-inspect להדפסה. גם each אמורה לעבוד ללא בלוק, ולהחזיר enumerator באמצעות 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 אונליין