Écrire des itérateurs

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

Exécuter un bloc de code

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!

Passage de paramètres

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

Implémentation de Carnet#chaque_personne

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! Implémentation de Carnet#chaque_adresse

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

Code complet de la classe Carnet

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

Implémentation du carnet d’adresses << | Apprenez Ruby | >> Autres fonctionnalités