Bonjour à tous. Dans cette séquence, nous allons nous
arrêter un petit peu sur les méthodes de classe.
Nous avons vu que les méthodes de classe sont des
méthodes normales, comme les autres.
En général, elles servent à créer de nouvelles instances
mais on peut s'en servir aussi pour d'autres choses.
On va voir 2 exemples à quoi des méthodes de classe peuvent servir.
Imaginons qu'on souhaite écrire un programme qui prend ce
texte-là en paramètre et qui crée
une structure. L'idée c'est que si une ligne commence par
un point d'exclamation, on considère que c'est un titre.
Si une ligne commence par un tiret, on considère que c'est
un item dans une liste.
Si ça commence par tiret tiret ou plus de tirets, on
considère que c'est un sous-élément d'une liste.
Autrement on considère que c'est un paragraphe.
On souhaite écrire un programme qui prend ça en entrée et
qui instancie les classes que vous voyez là, donc les
sous-classes de document et item.
On souhaite aussi, dans cette conception, que chaque
sous-classe document et item soient responsables de
parser les lignes et de décider si elles peuvent parser
ou pas une ligne donnée. Donc, si je regarde la méthode
canParse ici, on lui donne une ligne de texte.
Si cette ligne commence par un point d'exclamation, la
méthode canParse doit retourner vraie parce qu'on se
trouve dans la classe SectionTitle.
Dans la classe listeItem, la méthode can parse doit
retourner vraie si la ligne commence par un tiret, si la
ligne passée en paramètre commence par un tiret.
Et la méthode canParse, qui est ici, nous retournera systématiquement vraie.
L'idée c'est d'écrire un algorithme qui va regarder les
classes une par une, et dès qu'il y en a une qui retourne
canParse pour une ligne donnée, on va utiliser cette
classe-là pour en faire une nouvelle instance par rapport à cette ligne.
Donc, ça c'est le but de la méthode can parse et le but
de la méthode new from line, ça prend aussi une ligne en
paramètres, une ligne de texte en paramètres sauf que ça
va retourner une instance de la classe dans laquelle ça
vient d'être implémenté.
Donc, si j'envoie le message newFromLine à la classe
SectionTitle avec une chaîne de caractères qui commence
par un point d'exclamation, la méthode newFromLine va
retourner une instance de la classe SectionTitle.
Alors, comment ça se passe ?
C'est la classe Parser qui va être responsable de faire
ce travail-là et de chercher parmi les sous-classes de
documentItem quelle est celle qui va être responsable d'une
ligne en particulier.
La classe Parser possède une méthode document classes
dont la mission est de retourner la
liste des sous-classes de documentItem.
Donc, ça va retourner une collection qui contient cette
classe-là, cette classe-là et cette classe-là.
Pour ce faire, on envoie le message "allSupclasses" à "DocumentItem".
"allSup classes", c'est une méthode qui existe déjà dans
le système Pharo, qui retourne la liste des sous-classes
d'une classe donnée.
Là, en faisant ça, j'obtiens directement une collection
qui contient SectionTitle, listItem et Text.
Cette collection-la, je veux la trier
par priorité. L'idée c'est que la classe Text doit
arriver à la fin parce que sa méthode canParse retourne toujours vraie.
Donc, la classe Text peut parser n'importe quelle ligne.
On testera ça après avoir testé les autres.
On a cette notion de priorité, ici.
On voit que beaucoup de méthodes sont soulignées.
Si je souligne les méthodes ici, ça indique que ce sont
des méthodes de classe.
Pour exécuter ces méthodes-là, il faut envoyer des messages aux classes.
Il faut que j'envoie le message "CanParse" à la classe
section title pour savoir si la classe SectionTitle peut
parser une ligne donnée.
La méthode Parse de la classe parser prend une ligne en paramètres.
On va regarder dans l'ensemble des sous-classes de
documentItem s'il y a une classe qui est capable de
parser cette ligne-là, et si c'est le cas, va créer une
instance de cette classe. Le message détecte envoyer une
collection permet de trouver un
élément d'une collection parmi N suivant un prédicat.
Maintenant, on va s'intéresser à un autre exemple d'utilisation
de méthodes de classe.
On va s'intéresser à la lecture de paramètres de lignes de commande.
Donc, l'idée ici, c'est qu'on veut un programme qui s'il
reçoit des paramètres, qui va regarder quels sont les
paramètres et faire quelque chose différemment en fonction des paramètres.
Le premier paramètre indique l'action à exécuter.
Et ce qu'on va faire dans la conception de ce
programme-là, c'est qu'on va avoir une classe par type d'action.
L'action eval va être représentée par une classe, eval CommandLineHandler.
Quelle est l'action effectuée lorsque le
paramètre eval est présent ?
Ce qu'on va faire c'est qu'on va exécuter ce code-là, on
va interpréter cette chaîne de caractères-là comme du
code Pharo et retourner le résultat de ces expressions.
Le nombre qui est ici est le résultat de l'expression 10 factorial.
Comment est-ce qu'on implémente ça ?
On a une classe CommandLineHandler, une classe
EvaluateCommandHandler qui est une sous-classe dont le
but va être de traiter le paramètre eval.
Donc si le paramètre eval est envoyé comme premier
paramètre en ligne de commande, c'est cette classe-là qui doit travailler.
Donc, la méthode isResponsibleFor doit retourner Vraie si
une sous-classe est capable de prendre en compte la ligne
de commande. On voit, en-dessous, exactement le même
mécanisme qu'on a vu dans l'exemple précédent.
Là encore, on utilise des méthodes de classe et on envoie
des messages à des classes pour faire autre chose que créer des instances.
Donc on a vu 2 utilisations possibles des méthodes de classes.
Les méthodes de classe sont la plupart du temps utilisées
pour créer de nouvelles instances, mais elles peuvent
aussi être utilisées dans d'autres cas.