Escrevendo iteradores
Nesta seção, vamos adicionar nossos próprios iteradores à classe AddressBook. Vamos criar dois iteradores, AddressBook#each e AddressBook#each_address, que podem ser usados como de costume:
address_book.each do |person|
...
end
address_book.each_address do |address|
...
end
|
Chamando um bloco
Quando você escreve uma função ou método, você pode chamar um código com a palavra yield. Aqui está um exemplo.
def twice
yield
yield
end
twice { puts "Hello World" }
|
Isso mostra :
Hello World
Hello World
|
Passando parâmetros
Você pode usar o yield como qualquer outro método. Para passar parâmetros para o código, você simplesmente enviá-los ao yield. Veja este exemplo:
def names
yield("Joe")
yield("Sandy")
yield("Melissa")
end
names do |name|
puts "Hello " + name + ", how are you?"
end
|
Isso mostra na tela :
Hello Joe, how are you?
Hello Sandy, how are you?
Hello Melissa, how are you?
|
Você pode passar vários parâmetros para o bloco que você quiser. Por exemplo:
def full_names
yield("Joe", "Smith")
end
full_names do |first,last|
puts first + " " + last
end
|
Imprime:
Joe Smith
|
AddressBook#each
Agora podemos escrever o nosso primeiro iterator. AddressBook#each é o mais simples dos dois iteradores. Nós passamos por cada pessoa no array @persons e chamamos yield em cada um.
class AddressBook
def each
@persons.each { |p| yield p }
end
end
|
É isso. Agora nossa classe tem um iterador.
AddressBook#each_address
Este iterator é quase tão simples como o que escrevemos acima. Nós vamos passar por cada pessoa e em seu endereço.
class AddressBook
def each_address
@persons.each { |p| yield p.address }
end
end
|
Wrap up
Basta embrulhar tudo até agora. Aqui está toda a classe AddressBook juntamente com comentários. Trata-se de um pedaço de código bastante complexo, mas ao dividir a tarefa em partes menores nós a tornamos mais fáceis de gerenciar.
class AddressBook
#
# Fundamental methods: initialize, add, remove
#
def initialize
@persons = []
end
def add(person)
@persons += [person]
@persons = @persons.sort{|a,b| by_name(a,b)}
end
def remove(person)
@address.delete(person)
end
#
# Iterators: each, each_address
#
def each
@persons.each { |p| yield p }
end
def each_address
@persons.each { |p| yield p.address }
end
#
# Sorting function.
#
def by_name(a,b)
if a.first_name == b.first_name
a.last_name <=> b.last_name
else
a.first_name <=> b.first_name
end
end
end
|