Ruby/Méthodes (suite)
À partir de maintenant, nous allons distinguer deux usages de méthodes :
- Ce que nous avons vu dans la première partie, à savoir déclarer une méthode en dehors de toute classe. On pourra l’utiliser partout dans le fichier. Elle ne sera pas liée à un type d'objets particuliers.
- Ce que nous allons voir à présent, les méthodes d'instance. Elles sont définies pour tous les objets du type de cette classe (utilisables par toutes les instances). Pour les utiliser nous devons les appliquer à un objet du bon type.
Méthode d'instance
[modifier | modifier le wikicode]Déclaration d'une méthode d'instance
[modifier | modifier le wikicode]
Nous avons ici une classe Ordinateur
. Cette classe définit deux méthodes : boot
et shutdown
, disponibles pour les objets de type Ordinateur
. Comme vous pouvez le voir, la seule nouveauté est qu’elles sont définies à l'intérieur d'une classe (entre les mots-clés class
et end
).
Appel d'une méthode d'instance
[modifier | modifier le wikicode]Tout d’abord, instancions un objet de type Ordinateur :
Les méthodes définies plus haut s'appliquent à une instance d'objet. Nous devons donc, dans notre exemple, les invoquer sur l'instance laptop
en suivant le modèle : instance.méthode
.
Ce qui nous donne donc :
Mise à part cette nouveauté, les anciennes possibilités demeurent : vous pouvez passer des paramètres et récupérer une valeur de retour (pour l’utiliser dans une autre expression par exemple).
L'héritage
[modifier | modifier le wikicode]L'orientation objet de Ruby permet de faire hériter certaines classes d'autres classes. C'est là qu'intervient la notion de sous-classe. Cet exemple simple montre comment définir une classe héritant d'une super-classe :
Dans la définition de la classe Ordinateur
, < Machine
indique que cette classe est une sous-classe de la classe Machine
.
Par défaut, les sous-classes héritent des méthodes de leur super-classe : elles ont le même comportement. Mais l’intérêt est que vous pouvez vous servir des sous-classes pour modifier des méthodes ou en ajouter de nouvelles.
On pourrait donc enrichir notre classe Ordinateur
pour lui rajouter des méthodes par rapport à sa super-classe Machine
. L'héritage permet de spécialiser différemment des classes ayant un même tronc commun.
Vous pouvez modifier une classe (pour y ajouter des méthodes, par exemple) sans disposer de son code d'origine.
La méthode initialize
[modifier | modifier le wikicode]Lors de l'instanciation d'un nouvel objet (appel de new
), l'interpréteur vérifie si une méthode initialize
est associée à cet objet. Si c’est le cas il l'exécute.
class Ordinateur
def initialize
puts "Nouvel ordinateur !"
self.run
end
def run
puts "Hello world !"
end
end
monOrdi = Ordinateur.new
# => Nouvel ordinateur !
# => Hello world !
La méthode initialize
est presque une méthode comme les autres, elle peut prendre des paramètres, mais elle ne renvoie pas de valeur (enfin, elle renvoie une référence à l’objet instancié mais ce n’est pas exploitable).
Donc écrire self.run
(à l'intérieur de la classe) équivaut à écrire monOrdi.run
(à l'extérieur de la classe).
Dans d'autres langages, il y a un équivalent à la méthode initialize
, ce sont des constructeurs qui portent le même nom que la classe (en Java, par exemple).
Si la méthode initialize
n'a pas été trouvée dans la définition de la classe, l'interpréteur en cherche une dans les super-classes de la classe en question.
class GrandParent
def initialize
puts "visite :o)"
end
end
class Parent < GrandParent; end # sous-classe de GrandParent
class Enfant < Parent; end # sous-classe de Parent
me = Enfant.new # => visite :o)
Ici, la classe Enfant
ne dispose pas d'une méthode initialize
, on inspecte sa super-classe Parent
; elle n'en possède pas non plus, on va regarder du côté de sa super-classe GrandParent
; on appelle la méthode initialize
de la classe GrandParent
.
Redéfinition de méthodes
[modifier | modifier le wikicode]
Vous pouvez redéfinir des méthodes même si vous ne disposez pas du code de la classe.
Toutes les méthodes peuvent être redéfinie, initialize
ne fait pas exception.
La redéfinition peut aussi servir à différencier une méthode d'une sous-classe héritée de sa super-classe.
Voici par exemple deux classes : Machine
et Ordinateur
, la seconde héritant de la première :
class Machine
def run
puts "je suis une machine"
end
end
class Ordinateur < Machine
def run # on redéfinit la méthode run héritée de Machine
puts "je suis un ordinateur donc une machine"
end
end
objet1 = Machine.new
objet2 = Ordinateur.new
objet1.run # méthode originelle
objet2.run # méthode redéfinie
En invoquant la méthode run
sur l’objet de type Machine
, nous obtenons l’affichage produit par la méthode de la super-classe Machine
. La méthode redéfinie a été appelée lorsque nous avons invoqué run
sur l’objet de type Ordinateur
.
Appel de méthode de super-classe
[modifier | modifier le wikicode]Considérons deux classes Machine
et Ordinateur
(sous-classe de Machine
) disposant toutes deux d'une méthode run
:
class Machine
def run
puts "une machine"
end
end
class Ordinateur < Machine
def run
print "je suis un ordinateur donc "
super
end
end
Le mot-clé super
, placé au sein d'une méthode, nous permet d'appeler la méthode du même nom dans la super-classe.
super
peut être placé n’importe où dans la déclaration de votre méthode, et autant de fois que vous le voulez.
Ici, super
appelle la méthode run
de la classe Machine
.
Il appelle la méthode de la super-classe avec exactement les mêmes paramètres que la méthode dans laquelle il se trouve (dans notre exemple, il n'y en a aucun). Nous pouvons aussi choisir de n'en passer que quelques-uns, ou bien aucun. Dans ce dernier cas, l'appel à super
doit être suivi d'une paire de parenthèses vides :
def run(prix, poids)
super(poids) # seul le second paramètre est passé
super() # aucun paramètre n'est passé
end
Conclusion
[modifier | modifier le wikicode]Dans la documentation, vous trouverez des méthodes désignées comme suit :
NomClasse#Méthode
Cela vous permet de savoir sur quel type d'objet vous pouvez invoquer la méthode.
Par exemple : Integer#upto
vous informe qu’il existe une méthode upto
applicable à des objets de type Integer
(les entiers).