Maintenant, créons un objet de la classe `Greeter` et animons-le :

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):035:0&gt;</span><span class="w"> </span><span class="n">g</span> <span class="o">=</span> <span class="no">Greeter</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"Pat"</span><span class="p">)</span>
<span class="gp">=&gt; #&lt;Greeter:0x16cac @name="Pat"&gt;</span><span class="w">
</span><span class="gp">irb(main):036:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">say_hi</span>
<span class="go">Hi Pat!
</span><span class="p">=&gt;</span> <span class="kp">nil</span>
<span class="gp">irb(main):037:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">say_bye</span>
<span class="go">Bye Pat, come back soon.
</span><span class="p">=&gt;</span> <span class="kp">nil</span></code></pre></figure>

Une fois l’objet `g` créé, il se souvient que le nom qui lui est lié est
Pat, comme indiqué à sa création. Il serait d’ailleurs intéressant de
pouvoir récupérer directement ce nom. Essayons :

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):038:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="o">.</span><span class="vi">@name</span>
<span class="gr">SyntaxError: compile error
(irb):52: syntax error
        from (irb):52</span></code></pre></figure>

Whoa, ça n’a pas l’air possible pour l’instant.

## Dans la peau d’un objet

`name` est, comme nous l’avons vu, une variable d’instance. « Instance »
est synonyme d’objet. Les variables d’instances sont donc cachées au
cœur des objets que nous pouvons créer à loisir, en utilisant un modèle
générique, la classe. Mais elles ne sont pas si bien cachées que ça.
Pour commencer, vous pouvez les voir si vous *inspectez* un objet (avec
la méthode `inspect`), et il existe des moyens d’y accéder. Mais Ruby
fait en sorte de garder un peu d’ordre dans sa maison, et collant au
plus près de l’approche orientée objet, y compris dans la gestion des
données et variables qui les renferment.

Quelles sont les méthodes disponibles pour nos instances de la classe
`Greeter` ?

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):039:0&gt;</span><span class="w"> </span><span class="no">Greeter</span><span class="p">.</span><span class="nf">instance_methods</span>
<span class="p">=&gt;</span> <span class="p">[</span><span class="s2">"method"</span><span class="p">,</span> <span class="s2">"send"</span><span class="p">,</span> <span class="s2">"object_id"</span><span class="p">,</span> <span class="s2">"singleton_methods"</span><span class="p">,</span>
    <span class="s2">"__send__"</span><span class="p">,</span> <span class="s2">"equal?"</span><span class="p">,</span> <span class="s2">"taint"</span><span class="p">,</span> <span class="s2">"frozen?"</span><span class="p">,</span>
    <span class="s2">"instance_variable_get"</span><span class="p">,</span> <span class="s2">"kind_of?"</span><span class="p">,</span> <span class="s2">"to_a"</span><span class="p">,</span>
    <span class="s2">"instance_eval"</span><span class="p">,</span> <span class="s2">"type"</span><span class="p">,</span> <span class="s2">"protected_methods"</span><span class="p">,</span> <span class="s2">"extend"</span><span class="p">,</span>
    <span class="s2">"eql?"</span><span class="p">,</span> <span class="s2">"display"</span><span class="p">,</span> <span class="s2">"instance_variable_set"</span><span class="p">,</span> <span class="s2">"hash"</span><span class="p">,</span>
    <span class="s2">"is_a?"</span><span class="p">,</span> <span class="s2">"to_s"</span><span class="p">,</span> <span class="s2">"class"</span><span class="p">,</span> <span class="s2">"tainted?"</span><span class="p">,</span> <span class="s2">"private_methods"</span><span class="p">,</span>
    <span class="s2">"untaint"</span><span class="p">,</span> <span class="s2">"say_hi"</span><span class="p">,</span> <span class="s2">"id"</span><span class="p">,</span> <span class="s2">"inspect"</span><span class="p">,</span> <span class="s2">"=="</span><span class="p">,</span> <span class="s2">"==="</span><span class="p">,</span>
    <span class="s2">"clone"</span><span class="p">,</span> <span class="s2">"public_methods"</span><span class="p">,</span> <span class="s2">"respond_to?"</span><span class="p">,</span> <span class="s2">"freeze"</span><span class="p">,</span>
    <span class="s2">"say_bye"</span><span class="p">,</span> <span class="s2">"__id__"</span><span class="p">,</span> <span class="s2">"=~"</span><span class="p">,</span> <span class="s2">"methods"</span><span class="p">,</span> <span class="s2">"nil?"</span><span class="p">,</span> <span class="s2">"dup"</span><span class="p">,</span>
    <span class="s2">"instance_variables"</span><span class="p">,</span> <span class="s2">"instance_of?"</span><span class="p">]</span></code></pre></figure>

Ouch. Voilà une sacré liste de méthodes. Et pourtant, nous n’en avons
défini que deux… d’où sortent donc les autres ? En fait, il s’agit d’une
liste exhaustive des méthodes applicables aux objets de la classe
`Greeter`, y compris celles définies dans les classes *parentes* de
`Greeter`. Si nous voulons obtenir la listes des méthodes définies
uniquement pour `Greeter`, il suffit de passer le paramètre `false`\:

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):040:0&gt;</span><span class="w"> </span><span class="no">Greeter</span><span class="p">.</span><span class="nf">instance_methods</span><span class="p">(</span><span class="kp">false</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="p">[</span><span class="s2">"say_bye"</span><span class="p">,</span> <span class="s2">"say_hi"</span><span class="p">]</span></code></pre></figure>

Ok, c’est déjà plus confortable. Et conforme. Vérifions que c’est vrai,
en testant quelles méthodes reconnaissent effectivement les instances de
`Greeter`\:

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):041:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"name"</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="kp">false</span>
<span class="gp">irb(main):042:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"say_hi"</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="kp">true</span>
<span class="gp">irb(main):043:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"to_s"</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="kp">true</span></code></pre></figure>

Une instance de `Greeter` connaît donc `say_hi` et `to_s` (une méthode
qui transforme « quelque chose » en une chaîne de caractère et qui est
disponible pour tout objet). Par contre, la méthode `name` est inconnue.

## Modifier les classes *a posteriori*

Mais nous n’en démordrons pas : il nous *faut* un moyen de récupérer le
nom lié à un objet. Comment faire ? Ruby propose un moyen très simple
pour accéder aux variables d’instances :

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):044:0&gt;</span><span class="w"> </span><span class="k">class</span> <span class="nc">Greeter</span>
<span class="gp">irb(main):045:1&gt;</span><span class="w">   </span><span class="nb">attr_accessor</span> <span class="ss">:name</span>
<span class="gp">irb(main):046:1&gt;</span><span class="w"> </span><span class="k">end</span>
<span class="p">=&gt;</span> <span class="p">[</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:name</span><span class="o">=</span><span class="p">]</span></code></pre></figure>

Il semblerait que nous ayons défini une seconde fois la classe
`Greeter`... mais il n’en est rien. Nous l’avons simplement « ré-ouverte
» et modifiée. Et les changements ainsi définis sont immédiatement
disponibles dans tout objet nouvellement créé, ainsi que dans ceux déjà
existants ! Créons un nouvel objet et testons l’artifice :

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):047:0&gt;</span><span class="w"> </span><span class="n">g</span> <span class="o">=</span> <span class="no">Greeter</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"Andy"</span><span class="p">)</span>
<span class="gp">=&gt; #&lt;Greeter:0x3c9b0 @name="Andy"&gt;</span><span class="w">
</span><span class="gp">irb(main):048:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"name"</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="kp">true</span>
<span class="gp">irb(main):049:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"name="</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="kp">true</span>
<span class="gp">irb(main):050:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">say_hi</span>
<span class="go">Hi Andy!
</span><span class="p">=&gt;</span> <span class="kp">nil</span>
<span class="gp">irb(main):051:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">name</span><span class="o">=</span><span class="s2">"Betty"</span>
<span class="p">=&gt;</span> <span class="s2">"Betty"</span>
<span class="gp">irb(main):052:0&gt;</span><span class="w"> </span><span class="n">g</span>
<span class="gp">=&gt; #&lt;Greeter:0x3c9b0 @name="Betty"&gt;</span><span class="w">
</span><span class="gp">irb(main):053:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">name</span>
<span class="p">=&gt;</span> <span class="s2">"Betty"</span>
<span class="gp">irb(main):054:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">say_hi</span>
<span class="go">Hi Betty!
</span><span class="p">=&gt;</span> <span class="kp">nil</span></code></pre></figure>

Le fait d’écrire `attr_accessor` a implicitement défini deux nouvelles
méthodes à peu de frais : `name` pour récupérer la valeur de la
variable/objet `name`, et `name=` pour la définir et la modifier.

## Accueillir tout et tout le monde !

Le problème avec notre programme actuel, c’est qu’il ne peut s’occuper
que d’une seule personne à la fois. Il nous faut vraiment un…
SuperProgramme, qui pourrait aussi bien s’occuper de tout le monde en
une fois, que d’une seule personne ou de plusieurs personnes à la fois…

Comme notre programme commence à prendre de l’ampleur, arrêtons ici avec
IRB, et continuons dans un véritable éditeur de texte. Nous allons
enregistrer la suite dans un fichier. Pour quitter IRB, écrivez
simplement `quit`, `exit` ou appuyez sur \[Ctrl\]+\[D\].

Notre fichier va se présenter comme suit :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#!/usr/bin/env ruby</span>

<span class="k">class</span> <span class="nc">MegaGreeter</span>
  <span class="nb">attr_accessor</span> <span class="ss">:names</span>

  <span class="c1"># Création d'un objet</span>
  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">names</span> <span class="o">=</span> <span class="s2">"World"</span><span class="p">)</span>
    <span class="vi">@names</span> <span class="o">=</span> <span class="n">names</span>
  <span class="k">end</span>

  <span class="c1"># Saluer tout le monde</span>
  <span class="k">def</span> <span class="nf">say_hi</span>
    <span class="k">if</span> <span class="vi">@names</span><span class="p">.</span><span class="nf">nil?</span>
      <span class="nb">puts</span> <span class="s2">"..."</span>
    <span class="k">elsif</span> <span class="vi">@names</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"each"</span><span class="p">)</span>
      <span class="c1"># @names est une liste de noms : traitons-les uns par uns</span>
      <span class="vi">@names</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="nb">name</span><span class="o">|</span>
        <span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">!"</span>
      <span class="k">end</span>
    <span class="k">else</span>
      <span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">#{</span><span class="vi">@names</span><span class="si">}</span><span class="s2">!"</span>
    <span class="k">end</span>
  <span class="k">end</span>

  <span class="c1"># Dire au revoir à tout le monde</span>
  <span class="k">def</span> <span class="nf">say_bye</span>
    <span class="k">if</span> <span class="vi">@names</span><span class="p">.</span><span class="nf">nil?</span>
      <span class="nb">puts</span> <span class="s2">"..."</span>
    <span class="k">elsif</span> <span class="vi">@names</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"join"</span><span class="p">)</span>
      <span class="c1"># Grouper les différents noms de la liste par des virgules</span>
      <span class="nb">puts</span> <span class="s2">"Goodbye </span><span class="si">#{</span><span class="vi">@names</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s2">", "</span><span class="p">)</span><span class="si">}</span><span class="s2">.  Come back soon!"</span>
    <span class="k">else</span>
      <span class="nb">puts</span> <span class="s2">"Goodbye </span><span class="si">#{</span><span class="vi">@names</span><span class="si">}</span><span class="s2">.  Come back soon!"</span>
    <span class="k">end</span>
  <span class="k">end</span>

<span class="k">end</span>


<span class="k">if</span> <span class="kp">__FILE__</span> <span class="o">==</span> <span class="vg">$0</span>
  <span class="n">mg</span> <span class="o">=</span> <span class="no">MegaGreeter</span><span class="p">.</span><span class="nf">new</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_hi</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_bye</span>

  <span class="c1"># Modifier le nom en Zeke</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">names</span> <span class="o">=</span> <span class="s2">"Zeke"</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_hi</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_bye</span>

  <span class="c1"># Changer le nom pour un tableau (une liste de noms)</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">names</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"Albert"</span><span class="p">,</span> <span class="s2">"Brenda"</span><span class="p">,</span> <span class="s2">"Charles"</span><span class="p">,</span>
    <span class="s2">"Dave"</span><span class="p">,</span> <span class="s2">"Engelbert"</span><span class="p">]</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_hi</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_bye</span>

  <span class="c1"># Maintenant, le nom n'est plus...</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">names</span> <span class="o">=</span> <span class="kp">nil</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_hi</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_bye</span>
<span class="k">end</span></code></pre></figure>

Sauvegardez ce fichier, par exemple en tant que “ri20min.rb”
(l’extension .rb, pour ruby, est importante sous Windows, d’usage sous
les autres OS), et éxécutez-le en tapant “ruby ri20min.rb” dans votre
terminal. Vous devriez y lire ceci :

    Hello World!
    Goodbye World.  Come back soon!
    Hello Zeke!
    Goodbye Zeke.  Come back soon!
    Hello Albert!
    Hello Brenda!
    Hello Charles!
    Hello Dave!
    Hello Engelbert!
    Goodbye Albert, Brenda, Charles, Dave, Engelbert.  Come
    back soon!
    ...
    ...
{: .code}

Il y a un certain nombre de choses nouvelles dans ce fichier.
[Examinons-les en détails](../4/).
