Пользовательские коллекции
Часть раздела Объектно-ориентированное программирование путешествия по 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Задание
ЛегкоЗаверши класс 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}"
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовПеременные экземпляраМетоды и selfto_s и inspectПовторение — читательский билет4Инкапсуляция
Приватные методыЗащищённые методыПриватные сеттерыЗащита состоянияПовторение — торговый автомат7Полиморфизм и утиная типизация
ПолиморфизмУтиная типизацияАбстрактные методыcase и классыПовторение — способы оплаты10Шаблоны проектирования, часть 2
Делегирование с помощью ForwardableШаблон декоратораШаблон строителяШаблон состояния2Аксессоры и self
Чтение и записьПользовательские сеттерыself в методахИдентичность и равенствоПовторение — список контактов5Наследование
ПодклассыПереопределение методовВызов superis_a? и предкиПовторение — расчёт зарплаты сотрудников8Специальные методы
Равенство и хешированиеМетоды операторовИндексация и добавлениеПользовательские коллекцииПовторение — дроби11Проект: Управление библиотекой
Книги и читателиВыдача книг3Методы и переменные классов
Методы классовПеременные экземпляра классаКонстантыФабричные методыПовторение — коды купонов6Модули и примеси
Модули и includeРасширение объектовМодуль ComparableМодуль EnumerableПовторение — спортивная лига9Паттерны проектирования. Часть 1
Паттерн «Одиночка»Фабричный паттернПаттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Онлайн-компилятор Ruby