Tous les objets sont des instances de classe. Les classes sont des “moules”, les objets (ou instances de classe) sont des exemplaires de ce “moule”. On a déjà utilisé des classes basiques du type String, Fixnum ou Array.
Toutes les classes héritent de la classe Class, et cette dernière hérite de l’unique classe Object (vu que TOUT en Ruby est objet, même les classes). Donc on a, si on part du haut :
- la classe Object
- la classe Class
- toutes les autres classes (String, Array… et celles que l’on va créer)
Maintenant, on va créer nos propres classes.
Créer une classe
Pour créer sa propre classe, voici la syntaxe :
class MaClasse < Object end
On commencer par le mot “class”, on met le nom de classe en commençant par une majuscule, puis on met la classe “parente” (si il y en a une). Ici, j’ai mis que MaClasse héritait de la classe Object, mais c’est dans ce cas là inutile parce que par défaut, toutes les classes héritent de la classe Classe et donc de la classe Object.
Le fait d’hériter permet de récupérer toutes les méthodes et toutes les variables de la classe parente.
Méthodes et variables d’une classe
Lorsque l’on crée une classe, l’essentiel reste encore de créer des méthodes liées à cette classe, pour pouvoir en faire quelque chose!
La méthode “initialize”
Cette méthode est quasi-indispensable lorsque l’on crée une classe parce que c’est la méthode qui est appelée lorsque l’on crée une instance de la classe avec la méthode .new.
class Pilote def initialize(nom,prenom) puts "Je suis " + nom + " " + prenom + ", pilote de F1." end end nouveau_pilote = Pilote.new("Jenson","Button")
Là, je crée ma classe Pilote. Puis je crée la méthode initialize propre à ma classe Pilote.
Ensuite, en dehors de ma classe, je crée un objet “nouveau_pilote” (qui est une instance de ma classe Pilote) avec la méthode .new. En paramètre, je passe les mêmes paramètres que pour ma méthode initialize. Ce qu’il faut bien retenir c’est que la méthode .new appelle la méthode initialize de la classe Pilote.
Variables d’une classe
Une classe peut avoir des variables qui sont en réalité des variables d’instance. Ce sont donc des variables qui sont propres à chaque objet créé et qui peuvent contenir une valeur que l’on veut garder tout le long. Pour en créer une, il faut mettre un @ devant.
class Pilote def initialize(prenom,nom) @identite = prenom + " " + nom end def identite puts "Mon nom est " + @identite + "." end end pilote1 = Pilote.new("Jenson","Button") pilote1.identite → Mon nom est Jenson Button.
Ici, lors de le création de l’objet “pilote1″, je mets les valeurs “prenom” et “nom” (et un espace) dans ma variable d’instance “@identite”. De ce fait, je sauvegarde en quelque sorte les valeurs de “nom” et “prenom” et je peux utiliser la variable @identite plus loin.
Ces variables d’instance peuvent être pratiques si on modifie souvent une valeur de l’objet. Voici un exemple où la variable d’instance @matches change souvent.
class Equipe def initialize(nom,matches) @nom = nom @matches = matches end def joue_un_match @matches += 1 end def nbre_de_matches_joues puts "L'équipe " + @nom + " a joué " + @matches.to_s + " matches." end end girondins = Equipe.new("Girondins",0) girondins.joue_un_match girondins.joue_un_match girondins.joue_un_match girondins.nbre_de_matches_joues → L'équipe Girondins a joué 3 matches.
Ici, la variable d’instance @matches sauvegarde le nombre total de matches joués pendant la saison. A chaque fois que j’appelle la méthode “joue_un_match”, le nombre de matches augmente de 1. A la fin, je compte le nombre de matches joués : il est de 3. Par ailleurs, j’ai aussi “sauvegardé” le nom de l’équipe dans ma variable d’instance @nom.
Ces variables d’instance sont pratiques mais on ne peut y accéder de l’extérieur, donc on ne peut les lire directement ou les modifier. Pour cela, on va utiliser des attributs.
Attributs
Les attributs vont être des variables d’instance que l’on pourra lire et/ou éditer de l’extérieur (de la classe).
Des méthodes pour lire/éditer des attributs
class Equipe def initialize(nom,matches) @nom = nom @matches = matches end def pour_lire @popularite end def pour_editer=(taux) @popularite = taux end end girondins = Equipe.new("Girondins",0) girondins.pour_editer = 64 puts girondins.pour_lire → 64
(Ne faites pas attention à la méthode initialize, elle n’est pas importante ici)
Pour pouvoir lire un attribut, il suffit de créer une méthode qui renvoie la valeur de l’attribut. Etant donné que par défaut, une méthode renvoie la dernière valeur utilisée, ici ma méthode “pour_lire” renvoie la valeur de @popularite.
Pour pouvoir éditer attribut, il faut créer une méthode suivie du signe égal (=) avec un paramètre.
Je me rends compte que l’on peut tout à fait créer une méthode sans signe égal et appeler cette méthode avec le paramètre en paranthèse.
def pour_editer(taux) @popularite = taux end girondins.pour_editer(78)
Quoiqu’il en soit, il existe une manière plus rapide et plus lisible de créer des attributs.
Créer des attributs plus facilement
Voici les 2 lignes à écrire pour créer un attribut lisible et éditable de l’extérieur.
attr_reader :popularite attr_writer :popularite
Et si je réécris le code plus haut ici, cela donne :
class Equipe def initialize(nom,matches) @nom = nom @matches = matches end attr_reader :popularite attr_writer :popularite end girondins = Equipe.new("Girondins",0) girondins.popularite = 99 puts girondins.popularite → 99
Non seulement j’ai gagné beaucoup de place mais en plus, j’appelle la méthode .popularite qui n’est autre que le nom de mon attribut! Et le résultat est le même (mis à part que la côte de popularité des Girondins a bien augmenté en quelques paragraphes, mais c’est un effet secondaire totalement légitime).
J’ai juste 2 remarques à faire :
- cette orthographe attr_reader/attr_writer est plus synthétique mais offre moins de flexibilité qu’une méthode entière. Donc si vous voulez modifier ou lire plus en profondeur les attributs, il faudra utiliser une méthode (ce qui est tout à fait normal, c’est leur rôle!)
- faites attention à bien nommer les deux attributs du même nom, sinon vous écrirez un attribut et vous en lirez un autre. Peu pratique, à part si vous êtes maso.
Pour l’instant, toutes les méthodes créées pour la classe sont accessibles par tout le monde (même par IE6). Il va falloir engager un videur ou bien gérer l’accès avec les mots “public”, “private” et “protected”…
Flux RSS
Je suis avec attention ton apprentissage car le Ruby m’a toujours attiré, mais je n’ai jamais pris le temps de m’y mettre.
Je travaille beaucoup dans le monde du Java, et je suis un peu étonné que les variables d’instance de classe soient initialisées dans le constructeur plutôt qu’en dehors. J’trouve ça un tout petit peu sale (certainement une question d’habitude).
J’ai vu aussi que dans le monde Ruby on différenciaient variables d’instances (@) des variables de classe (@@). C’est un peu étrange… Je ne vois pas l’intérêt des @@ en fait. Enfin tu l’expliquera peut-être dans un futur article
Bon apprentissage !
Hello
Je pense que l’on peut initialiser les variables d’instance en dehors du constructeur. Je l’ai fait ici parce que dans l’exemple donné c’était comme ça. Il faudra que j’essaye. Je suis quasiment sûr que c’est possible.
Aussi, la syntaxe de mes exemples n’est pas forcément la plus optimale. Au fur et à mesure de mon apprentissage, mon code deviendra de plus en plus propre.
Cool :]
En tout cas, je kiffe le concept.