Au premier coup d’œil, Ruby vous rappellera certainement les autres
langages que vous avez déjà pu utiliser. Rien de plus normal : une bonne
partie de la syntaxe se rapproche de Perl, de Python et de Java (entre
autres), de sorte que si vous venez d’un de ces langages, apprendre Ruby
devrait être plutôt facile.
{: .summary}

Le présent document se partage en deux grandes sections. En premier
lieu, une revue rapide de ce à quoi vous pouvez vous attendre en passant
d’un langage donné à Ruby. Dans un deuxième temps, un examen plus
approfondi des fonctionnalités propres de Ruby, illustré de quelques
comparaisons avec d’autres langages.

## À quoi s’attendre : passer d’un langage X à Ruby

* [De C/C++ à Ruby](to-ruby-from-c-and-cpp/)
* [De Java à Ruby](to-ruby-from-java/)
* [De Perl à Ruby](to-ruby-from-perl/)
* [De PHP à Ruby](to-ruby-from-php/)
* [De Python à Ruby](to-ruby-from-python/)

## Les fonctionnalités importantes et autres astuces

Voici un aperçu et des conseils concernant les fonctionnalités majeures
de Ruby que vous allez rencontrer au cours de votre apprentissage.

### Itération

Représentant en général une nouveauté technique pour celui qui découvre
Ruby, les blocs et les itérateurs demandent en général un petit temps
d’adaptation. Au lieu de construire une boucle sur un index (comme en C,
C++ ou java &lt; 1.5) ou sur une liste (comme en Perl, avec
`for (@a) {...}`, ou en Python, avec `for i in Liste: ...`),
vous écrirez souvent en Ruby quelque chose comme :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">une_liste</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">item_courant</span><span class="o">|</span>
  <span class="c1"># Nous sommes dans le bloc.</span>
  <span class="c1"># Travaillons avec l'item_courant de la liste...</span>
<span class="k">end</span></code></pre></figure>

Pour plus d’informations sur `each` et ses méthodes apparentées
(`collect`, `find@n @inject`, `sort`, etc.), voyez `ri Enumerable` dans
un terminal, par exemple (affinez ensuite avec `ri Enumerable#méthode`).

### Des valeurs, partout

Ruby ne fait pas de différence entre une expression et une déclaration.
Tout ce qui existe possède intrinsèquement une valeur, même si cette
valeur est **nil** (qui *modélise* l’absence de valeur). De ce fait, ce
qui suit est possible :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">x</span> <span class="o">=</span> <span class="mi">10</span>
<span class="n">y</span> <span class="o">=</span> <span class="mi">11</span>
<span class="n">z</span> <span class="o">=</span> <span class="k">if</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">y</span>
      <span class="kp">true</span>
    <span class="k">else</span>
      <span class="kp">false</span>
    <span class="k">end</span>
<span class="n">z</span> <span class="c1"># =&gt; true</span></code></pre></figure>

### Les symboles ne sont pas des chaînes allégées

Beaucoup de débutants en Ruby se débattent longtemps avec la nature
*exacte* des symboles, et la pertinence de leur utilisation.

La meilleure façon de décrire les symboles seraient de dire qu’ils sont
des identités. Un symbole porte essentiellement sur le **qui**, et non
sur le *ce que*—il ne s’agit pas de déterminer la nature de ce qui est,
mais bien de savoir ce qui est. Le test suivant dans IRB illustre la
notion :

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):001:0&gt;</span><span class="w"> </span><span class="ss">:george</span><span class="p">.</span><span class="nf">object_id</span> <span class="o">==</span> <span class="ss">:george</span><span class="p">.</span><span class="nf">object_id</span>
<span class="p">=&gt;</span> <span class="kp">true</span>
<span class="gp">irb(main):002:0&gt;</span><span class="w"> </span><span class="s2">"george"</span><span class="p">.</span><span class="nf">object_id</span> <span class="o">==</span> <span class="s2">"george"</span><span class="p">.</span><span class="nf">object_id</span>
<span class="p">=&gt;</span> <span class="kp">false</span>
<span class="gp">irb(main):003:0&gt;</span></code></pre></figure>

La méthode `object_id` retourne l’identité d’un objet donné. Si deux
objets ont la même identité, alors il s’agit d’un seul et même objet
(même allocation mémoire).

Comme vous pouvez le voir, une fois un symbole défini, tout symbole de
mêmes caractères (même nom) fait référence au même objet en mémoire.
Pour deux symboles donnés représentant les mêmes caractères,
l’`object_id` est unique.

Voyez maintenant le résultat obtenu sur la chaîne de caractères
“george”. L’`object_id` ne correspond pas. Cela signifie qu’il y a bien
deux objets différents, qui se ressemblent, mais qui n’ont pas la même
identité. À chaque fois qu’une chaîne de caractère est utilisée, Ruby
réalise une nouvelle allocation en mémoire.

Si vous doutez quant à l’utilisation d’un symbole ou d’une chaîne,
estimez ce qui est dans votre cas le plus important : l’identité de
l’objet (par exemple, la clé d’un hash) ou son contenu (par exemple, «
george »).

### Tout est un objet

En Ruby, l’expression « orienté objet » n’est pas une hyperbole.
Jusqu’aux classes et aux entiers, tout ce qui est manipulable est un
objet à part entière—objet acceptant les manipulations usuelles du type
:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># Voici un bout de code équivalent à :</span>
<span class="c1"># class MaClass</span>
<span class="c1">#   attr_accessor :var_instance</span>
<span class="c1"># end</span>
<span class="no">MaClass</span> <span class="o">=</span> <span class="no">Class</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
  <span class="nb">attr_accessor</span> <span class="ss">:var_instance</span>
<span class="k">end</span></code></pre></figure>

### Des constantes variables

Ce qu’on appele habituellement constante ne l’est pas vraiment, en Ruby.
La modification d’une constante est possible : elle produit un
avertissement, mais ne stopppe pas l’exécution du programme. Ce qui n’es
pas un encouragement en soi à redéfinir les constantes, cela dit.

### Conventions de nommages

Ruby intègre (et impose) des conventions de nommage sémantiques. Si un
identifiant commence par une majuscule, il s’agit d’une constante. S’il
débute par un signe dollar (`$`), c’est une variable globale. S’il débute
par un `@`, il s’agit d’une variable d’instance. S’il commence par `@@`,
c’est une variable de classe.

Les noms de méthodes peuvent débuter par une majuscule—mais cela peut
conduire à des confusions, comme dans l’exemple qui suit :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">Constante</span> <span class="o">=</span> <span class="mi">10</span>
<span class="k">def</span> <span class="nf">Constante</span>
  <span class="mi">11</span>
<span class="k">end</span></code></pre></figure>

`Constante` vaut 10, mais `Constante()` vaut 11.

### Paramètres « mot-clés »

Depuis Ruby 2.0, à l'instar de Python, il est possible de définir une
méthode avec des paramètres « mot-clés » :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">deliver</span><span class="p">(</span><span class="ss">from: </span><span class="s2">"A"</span><span class="p">,</span> <span class="ss">to: </span><span class="kp">nil</span><span class="p">,</span> <span class="ss">via: </span><span class="s2">"mail"</span><span class="p">)</span>
  <span class="s2">"Sending from </span><span class="si">#{</span><span class="n">from</span><span class="si">}</span><span class="s2"> to </span><span class="si">#{</span><span class="n">to</span><span class="si">}</span><span class="s2"> via </span><span class="si">#{</span><span class="n">via</span><span class="si">}</span><span class="s2">."</span>
<span class="k">end</span>

<span class="n">deliver</span><span class="p">(</span><span class="ss">to: </span><span class="s2">"B"</span><span class="p">)</span>
<span class="c1"># =&gt; "Sending from A to B via mail."</span>
<span class="n">deliver</span><span class="p">(</span><span class="ss">via: </span><span class="s2">"Pony Express"</span><span class="p">,</span> <span class="ss">from: </span><span class="s2">"B"</span><span class="p">,</span> <span class="ss">to: </span><span class="s2">"A"</span><span class="p">)</span>
<span class="c1"># =&gt; "Sending from B to A via Pony Express."</span></code></pre></figure>

### La vérité, toujours la vérité

En Ruby, tout ce qui n’est pas **nil** ou **false** est considéré comme
vrai (**true**). En C, Python et dans bien d’autres langages, le 0 et
d’autres valeurs (telles les listes vides) sont considérées fausses.
Voyez par exemple le bout de code suivant, écrit en Python :

<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1"># en Python
</span><span class="k">if</span> <span class="mi">0</span><span class="p">:</span>
  <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">0 est vrai/true</span><span class="sh">"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
  <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">0 est faux/false</span><span class="sh">"</span><span class="p">)</span></code></pre></figure>

Ce qui affichera « 0 est faux/false. » L’équivalent en Ruby, maintenant :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># en Ruby</span>
<span class="k">if</span> <span class="mi">0</span>
  <span class="nb">puts</span> <span class="s2">"0 est vrai/true"</span>
<span class="k">else</span>
  <span class="nb">puts</span> <span class="s2">"0 est faux/false"</span>
<span class="k">end</span></code></pre></figure>

Cette fois, vous lirez « 0 est vrai/true. »

### Les modifications d’accès sont actives jusqu’à preuve du contraire

Considérez le bout de code suivant :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">MyClass</span>
  <span class="kp">private</span>
  <span class="k">def</span> <span class="nf">a_method</span><span class="p">;</span> <span class="kp">true</span><span class="p">;</span> <span class="k">end</span>
  <span class="k">def</span> <span class="nf">another_method</span><span class="p">;</span> <span class="kp">false</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

Vous pourriez vous attendre à ce que `another_method` soit publique. Ce
n’est pas le cas. Le mot-clé `private` est effectif jusqu’à la fin de la
portée actuelle (ici, la classe `MyClass`), ou jusqu’à ce qu’un autre
mot-clé change la donne. Par défaut, les méthodes sont publiques :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">MyClass</span>
  <span class="c1"># Méthode implicitement publique</span>
  <span class="k">def</span> <span class="nf">a_method</span><span class="p">;</span> <span class="kp">true</span><span class="p">;</span> <span class="k">end</span>

  <span class="kp">private</span>

  <span class="c1"># Cette méthode est privée</span>
  <span class="k">def</span> <span class="nf">another_method</span><span class="p">;</span> <span class="kp">false</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

`public`, `private` et `protected` sont des méthodes à part entière,
elles peuvent prendre des paramètres. Si vous passez un symbole à l’une
d’elle, la visibilité de cette méthode est modifiée.

### Accès aux méthodes

En Java, `public` signifie qu’une méthode est accessible par tout un
chacun. `protected` signifie que les instances de la classe, les
instances de classes filles et les instances de classes du même paquet
peuvent y accéder, à l’exclusion de tout autre domaine. `private`
signifie que personne à part les instances de la classe ne peut accéder
à la méthode.

Ruby se démarque un peu ici. `public` signifie la même chose, mais
`private` signifie que les méthodes sont accessibles uniquement si elles
peuvent être appelées sans destinataire explicite. En fait, seul `self`
est autorisé. `protected` est à part : une méthode protégée peut être
appelée depuis une instance de classe ou de classe fille, mais également
avec une autre instance comme destinataire.

Un exemple, repris de la [FAQ Ruby][faq]:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">Test</span>
  <span class="c1"># publique par défaut</span>
  <span class="k">def</span> <span class="nf">identifier</span>
    <span class="mi">99</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">==</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
    <span class="n">identifier</span> <span class="o">==</span> <span class="n">other</span><span class="p">.</span><span class="nf">identifier</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="n">t1</span> <span class="o">=</span> <span class="no">Test</span><span class="p">.</span><span class="nf">new</span>  <span class="c1"># =&gt; #&lt;Test:0x34ab50&gt;</span>
<span class="n">t2</span> <span class="o">=</span> <span class="no">Test</span><span class="p">.</span><span class="nf">new</span>  <span class="c1"># =&gt; #&lt;Test:0x342784&gt;</span>
<span class="n">t1</span> <span class="o">==</span> <span class="n">t2</span>       <span class="c1"># =&gt; true</span>

<span class="c1"># passer `identifier' en protected fonctionne toujours :</span>
<span class="c1"># la référence à other est autorisée</span>

<span class="k">class</span> <span class="nc">Test</span>
  <span class="kp">protected</span> <span class="ss">:identifier</span>
<span class="k">end</span>

<span class="n">t1</span> <span class="o">==</span> <span class="n">t2</span>  <span class="c1"># =&gt; true</span>

<span class="c1"># par contre, si `identifier' est private...</span>

<span class="k">class</span> <span class="nc">Test</span>
  <span class="kp">private</span> <span class="ss">:identifier</span>
<span class="k">end</span>

<span class="n">t1</span> <span class="o">==</span> <span class="n">t2</span>
<span class="c1"># NoMethodError: private method `identifier' called for #&lt;Test:0x342784&gt;</span></code></pre></figure>

### Les classes restent ouvertes

Ouvertes à la modification, à tout moment. Vous pouvez y faire des
ajouts, les modifier durant l’exécution. Y compris les classes
standards, telles que `Integer`, voire `Object`, la classe parente de
toute autre. Par exemple, l’application Ruby on Rails défini nombre de
méthodes pour traiter le temps, au sein de `Integer`. Voyez ceci :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">Integer</span>
  <span class="k">def</span> <span class="nf">hours</span>
    <span class="nb">self</span> <span class="o">*</span> <span class="mi">3600</span> <span class="c1"># nombre de secondes dans une heure</span>
  <span class="k">end</span>
  <span class="k">alias</span> <span class="n">hour</span> <span class="n">hours</span>
<span class="k">end</span>

<span class="c1"># 14 heures après le 1er janvier à 00h00</span>
<span class="no">Time</span><span class="p">.</span><span class="nf">mktime</span><span class="p">(</span><span class="mi">2006</span><span class="p">,</span> <span class="mo">01</span><span class="p">,</span> <span class="mo">01</span><span class="p">)</span> <span class="o">+</span> <span class="mi">14</span><span class="p">.</span><span class="nf">hours</span> <span class="c1"># =&gt; Sun Jan 01 14:00:00</span></code></pre></figure>

### Indices sémantiques sur les méthodes

Un nom de méthode en Ruby peut se terminer par un point d’interrogation
ou d’exclamation. Le premier signe de ponctuation sera utilisé pour les
méthodes qui donnent une réponse à une question (par exemple,
`Array#empty?`, qui retourne `true` si le destinataire est vide). Les
méthodes potentiellement « dangereuses » (parce qu’elles modifient
`self` ou les paramètres, comme `exit!`) sont signalées par le second
signe.

Mais ce n’est pas obligatoire, et parfois le choix a été de ne rien
indiquer du tout. Ainsi, `Array#replace` modifie sur place le contenu
d’un tableau avec le contenu d’un autre tableau.

### Les méthodes singletons

Une méthode singleton est une méthode liée à *un* objet. Elle n’est
disponible que pour l’objet défini.

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">Car</span>
  <span class="k">def</span> <span class="nf">inspect</span>
    <span class="s2">"Cheap car"</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="n">porsche</span> <span class="o">=</span> <span class="no">Car</span><span class="p">.</span><span class="nf">new</span>
<span class="n">porsche</span><span class="p">.</span><span class="nf">inspect</span> <span class="c1"># =&gt; Cheap car</span>
<span class="k">def</span> <span class="nc">porsche</span><span class="o">.</span><span class="nf">inspect</span>
  <span class="s2">"Expensive car"</span>
<span class="k">end</span>

<span class="n">porsche</span><span class="p">.</span><span class="nf">inspect</span> <span class="c1"># =&gt; Expensive car</span>

<span class="c1"># Les autres objets ne sont pas affectés</span>
<span class="n">other_car</span> <span class="o">=</span> <span class="no">Car</span><span class="p">.</span><span class="nf">new</span>
<span class="n">other_car</span><span class="p">.</span><span class="nf">inspect</span> <span class="c1"># =&gt; Cheap car</span></code></pre></figure>

### Gestion des méthodes manquantes

Si un message ne correspond pas à une méthode explicitement définie,
Ruby n’abandonne pas la partie et passe la main à la méthode nommée
`method_missing`. Elle l’informe du nom de la méthode introuvable et des
éventuels paramètres joints au message. Par défaut, `method_missing`
lève une exception du type NameError, mais vous pouvez la redéfinir pour
mieux l’intégrer au contexte de votre application—de nombreuses
bibliothèques exploitent cette possibilité. Voici un exemple :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># id est le nom de la méthode appelée, la syntaxe * renvoie</span>
<span class="c1"># tous les paramètres dans un tableau nommé « arguments »</span>
<span class="k">def</span> <span class="nf">method_missing</span><span class="p">(</span><span class="nb">id</span><span class="p">,</span> <span class="o">*</span><span class="n">arguments</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">"La méthode </span><span class="si">#{</span><span class="nb">id</span><span class="si">}</span><span class="s2"> a été appelée, mais elle n'existe pas. "</span> <span class="o">+</span>
       <span class="s2">"Voici les paramètres de l'appel : </span><span class="si">#{</span><span class="n">arguments</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">"</span>
<span class="k">end</span>

<span class="n">__</span> <span class="ss">:a</span><span class="p">,</span> <span class="ss">:b</span><span class="p">,</span> <span class="mi">10</span>
<span class="c1"># =&gt; La méthode __ a été appelée, mais elle n'existe pas. Voici les paramètres de l'appel :</span>
<span class="c1"># arguments: a, b, 10</span></code></pre></figure>

Le code ci-dessus ne fait qu’afficher les détails de l’appel, mais vous
êtes libres de manipuler tout ça à votre guise.

###  *Envoi de message* et non appel de fonction

Ce qui est communément appelé « appel de méthode » est bel et bien *un
message envoyé* à un autre objet—voyez plutôt :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># Ceci...</span>
<span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span>
<span class="c1"># est équivalent à...</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">+</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="c1"># qui est la même chose que :</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">send</span> <span class="s2">"+"</span><span class="p">,</span> <span class="mi">2</span></code></pre></figure>

### Les blocs aussi sont des objets—bien qu’ils ne le sachent pas (encore)

Les blocs (*closures*) sont massivement utilisés dans la bibliothèque
standard. Pour appeler un bloc, vous pouvez utiliser `yield`, ou bien le
transformer en `Proc` en rajoutant un paramètre spécial à la liste
d’arguments, comme ceci :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">bloc</span><span class="p">(</span><span class="o">&amp;</span><span class="n">le_bloc</span><span class="p">)</span>
  <span class="c1"># Ici, dedans, le_bloc est le bloc passé à la méthode</span>
  <span class="n">le_bloc</span> <span class="c1"># retourne le bloc</span>
<span class="k">end</span>
<span class="n">addition</span> <span class="o">=</span> <span class="n">bloc</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">|</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span> <span class="p">}</span>
<span class="c1"># addition est maintenant un objet du genre Proc</span>
<span class="n">addition</span><span class="p">.</span><span class="nf">class</span> <span class="c1"># =&gt; Proc</span></code></pre></figure>

Cela signifie que vous pouvez créer des blocs en-dehors du contexte des
appels de méthode, en utilisant `Proc.new` avec un bloc ou en appelant
une méthode `lambda`.

De la même façon, les méthodes sont également des objets bien réels :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">method</span><span class="p">(</span><span class="ss">:puts</span><span class="p">).</span><span class="nf">call</span> <span class="s2">"puts est un objet !"</span>
<span class="c1"># =&gt; puts est un objet !</span></code></pre></figure>

### Opérer sur les opérateurs

La plupart des opérateurs ne sont là que pour faciliter la vie du
programmeur (et gèrent aussi les règles de priorité mathématique). Vous
pouvez, par exemple, redéfinir la méthode `+` de la classe `Integer`\:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">Integer</span>
  <span class="c1"># Possible, mais pas recommandé...</span>
  <span class="k">def</span> <span class="nf">+</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
    <span class="nb">self</span> <span class="o">-</span> <span class="n">other</span>
  <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

Pas besoin des `operator+` comme en C++, etc.

Vous pouvez aussi créer des accès du type tableau en définissant les
méthodes `[]` et `[]=`. Pour définir les signes + et -, comme pour +1 et
-2, vous définirez les méthodes `+`@ et `-`@, respectivement.

Les opérateurs ci-dessous ne sont pas des méthodes, et ne peuvent pas
être modifiés :

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="o">=</span><span class="p">,</span> <span class="o">..</span><span class="p">,</span> <span class="o">...</span><span class="p">,</span> <span class="ow">not</span><span class="p">,</span> <span class="o">&amp;&amp;</span><span class="p">,</span> <span class="ow">and</span><span class="p">,</span> <span class="o">||</span><span class="p">,</span> <span class="ow">or</span><span class="p">,</span> <span class="o">::</span></code></pre></figure>

Par ailleurs, `+=`, `*=`, etc. ne sont que des raccourcis pour
`var = var + autre_var`, `var = var * autre_var`, etc. et ne peuvent
être redéfinis.

## En savoir (encore) plus

Enthousiaste ? Direction notre section
[Documentation](/fr/documentation/).



[faq]: http://ruby-doc.org/docs/ruby-doc-bundle/FAQ/FAQ.html
