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