Dans cette section, nous allons ajouter deux itérateurs dans la classe Carnet: Carnet#chaque_personne et Carnet#chaque_adresse. Au résultat, nous pourrons écrire ceci:
carnet.chaque_personne do |personne|
# ...
end
carnet.chaque_adresse do |adresse|
# ...
end
Le mot clef yield permet d'appeler un bloc de code. Voici un exemple:
def deux_fois
yield
yield
end
deux_fois { puts "Vive Ruby!" }
Ce qui produira:
Vive Ruby! Vive Ruby!
Vous pouvez utiliser yield exactement comme n'importe quelle autre méthode. Pour passer des arguments à un bloc de code, passez-les simplement à yield. Prenez cet exemple:
def noms
yield("Nicolas")
yield("François")
yield("Marina")
end
noms do |nom|
puts "Salut " + nom + ", comment vas-tu?"
end
Ce qui affichera à l'écran:
Salut Nicolas, comment vas-tu? Salut François, comment vas-tu? Salut Marina, comment vas-tu?
Vous pouvez passez autant de paramètres que vous voulez au bloc de code. Par exemple:
def noms
yield("Nicolas Rocher")
end
noms do |prenom, nom|
puts prenom + " " + nom
end
Ce qui donnera:
Nicolas Rocher
Ce premier itérateur est le plus facile des deux à écrire: il suffit simplement de parcourir chaque personne dans le tableau @personnes et d'appeler yield sur chaque élément:
class Carnet
# ...
def chaque_personne
@personnes.each { |p| yield(p) }
end
end
Et voila!
Cet itérateur est quasi aussi simple à écrire que le premier. Au lieu de passer chaque personne au bloc de code, nous allons passer l'adresse de cette personne:
class Carnet
# ...
def chaque_adresse
@personnes.each { |p| yield(p.adresse) }
end
end
Juste pour tout mettre au clair, voici le code complet commenté de la classe Carnet. Il s'agit d'un morceau de code assez complexe, mais en découpant les tâches au fur et à mesure, il est beaucoup plus facile à maintenir:
class Carnet
#
# Méthodes fondamentales:
# initialize
# ajoute
# retire
#
def initialize
@personnes = []
end
def ajoute(personne)
@personnes.push(personne)
@personnes = @personnes.sort { |a, b| par_nom(a, b) }
end
def remove(personne)
@personnes.delete(personne)
end
#
# Iterateurs:
# chaque_personne
# chaque_adresse
#
def chaque_personne
@personnes.each { |p| yield p }
end
def chaque_adresse
@personnes.each { |p| yield p.adresse }
end
#
# Fonction de tri.
#
def par_nom(a, b)
if a.prenom == b.prenom
a.nom <=> b.nom
else
a.prenom <=> b.prenom
end
end
end