Ruby et les eigenclass
Dans l’
article d’hier,
je cherchais un intérêt à class << self
dans la
définition d’une classe, et je n’en ai pas trouvé.
Aujourd’hui je vais appronfondir le sujet et parler des eigenclass(es) en Ruby.
Il se trouve que Ruby est un langage orienté objet, contrairement à…
(au hasard) Java…
Ok, c’est pour rire. Bien sûr que Java est un langage OO. Mais quand même, par rapport à Ruby je dirais plutôt que Java est un langage orienté classe. Avec Ruby, tout est objet, même les classes ! Je re-dis ça autrement pour que ce soit bien clair : en Ruby les classes sont des objets comme les autres. Voyons comment ça fonctionne, au travers des eigenclass(es):
On a créé une classe Engin
et instancié deux objets à partir de cette
classe, voiture
et moto
. La classe a joué le rôle d’un moule, à partir
duquel les deux objets ont été fabriqués et leurs comportements sont
identiques. Maintenant, si on veut spécialiser le comportement de moto
,
on pourrait utiliser l’héritage ou les mixins. Ce qui serait très bien si
on devait gérer des dizaines d’objets au comportement similaire. Mais si on
a un seul objet qui diffère, devoir écrire une nouvelle classe pour un seul
objet est un peu lourd. Grâce au eigenclass(es), Ruby permet de changer le
comportement d’un objet pendant l’execution.
Ou bien avec la syntaxe suivante, qui fait la même chose:
On vient d’ajouter une méthode à l’objet moto
de classe Engin
, mais pas
à l’objet voiture
, pourtant lui aussi de classe Engin
. Pour vérifier:
Comment Ruby gère ce système ? C’est surprenant de simplicité. Ruby interpose
une nouvelle classe, anonyme, entre l’objet et sa hiérarchie de classes. C’est
cette nouvelle classe, qu’on appelle eigenclass.
L’eigenclass ne comprend que les comportements ajoutés à «son» objet. Dans
notre exemple, l’eigenclass de moto
ne comporte que la méthode wheeling
.
Le système de classe de Ruby est complexe, mais pour la partie qui nous
intéresse ici cela donne ça:
moto < eigenclass < Engin < Object
À la place de «eigenclass», on peut lire et entendre parfois «singleton» ou
«metaclass», c’est la même chose. D’ailleurs, pour obtenir la liste des
méthodes de la «ghost class» (encore un autre nom) on peut utiliser la
méthode singleton_methods
:
J’ai dit au début qu’une classe est un objet comme un autre. Donc ce qui
fonctionne pour moto
doit aussi fonctionner pour Engin
:
Tout pareil ! definition
a été ajouté à l’eigenclass de Engin
.
Autrement dit, quand vous ajouter une méthode de classe à une classe, en fait
vous l’ajouter à son eigenclass.
À demain.