Coleções Personalizadas
Parte da seção Programação orientada a objetos do Journey de Ruby da Coddy. Lição 40 de 57.
Uma classe de coleção combina vários métodos especiais: each com Enumerable, << para adicionar, size e to_s e inspect para imprimir. each também deve funcionar sem um bloco, retornando um enumerador com to_enum, assim como os arrays:
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") }Saída:
1. wash
2. shop
3. cook
["shop", "cook"]block_given? informa se o chamador passou um bloco. O enumerador retornado sem um bloco permite encadeamentos como each.with_index, each_slice ou 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_aSaída:
3
2
[[5, 4], [3, 2], [1]]to_s é o texto amigável para os usuários, e inspect, um resumo curto para programadores. Para uma coleção, inspect geralmente mostra a classe e o tamanho, em vez de cada elemento:
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 listSaída:
1. wash
2. shop
#<TodoList 2 itens>Enumerable fornece count, mas não size, empty?, << ou []: eles pertencem à classe, pois somente ela sabe como os elementos são armazenados. Defini-los faz a coleção parecer um array para quem a utiliza:
def size
@items.size
end
def empty?
@items.empty?
end
def [](index)
@items[index]
endDesafio
FácilComplete a classe TodoList. << adiciona o texto de uma tarefa e retorna a lista. each produz as tarefas e retorna to_enum(:each) sem um bloco. Inclua Enumerable. size retorna o número de tarefas. to_s retorna as tarefas como linhas numeradas, 1. wash, ou nothing to do, e inspect retorna #<TodoList 3 items>.
O código fornecido adiciona cada linha de entrada encadeando <<, depois imprime a lista, o resultado de p da lista, as tarefas numeradas com ! por meio de each.with_index(1) como 1! wash, o número de tarefas que contêm o e a primeira tarefa em ordem alfabética.
Seu código deve ficar em todo_list.rb. main.rb contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
require_relative 'todo_list'
# Código de entrada/saída fornecido: mantenha-o como está
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}"
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação orientada a objetos
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesVariáveis de InstânciaMétodos e selfto_s e inspectRevisão - Cartão da Biblioteca4Encapsulamento
Métodos privadosMétodos protegidosSetters privadosProtegendo o estadoRevisão - Máquina de venda automática7Polimorfismo e Duck Typing
PolimorfismoDuck TypingMétodos Abstratoscase e ClassesRevisão - Métodos de Pagamento2Acessores e self
Leitores e GravadoresSetters Personalizadosself nos MétodosIdentidade e IgualdadeRecapitulação - Lista de Contatos5Herança
SubclassesSobrescrita de métodosChamando superis_a? e ancestraisRevisão - Folha de pagamento da equipe8Métodos Especiais
Igualdade e hashMétodos de OperadoresIndexação e AdiçãoColeções PersonalizadasRevisão - Frações11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Compilador de Ruby online