Dans cette séquence nous allons parler des méthodes de classe.
Alors en Pharo nous avons vu tout est un objet et qu'on pouvait envoyer des messages et des objets.
Si on prend ces 2 informations-là, les classes sont aussi des objets et on peut envoyer les informations à des classes donc on peut envoyer des messages à des classes.
Ci dessous deux exemples:
Time now
On envoie le message now
à l'objet Time
qui est un nom de classe, qui est une classe, ça me renvoie l'heure actuelle.
Date today
De la même façon, j'envoie le message today à l'objet Date qui est une classe, et ça me retourne la date du jour.
Voici trois autres exemples:
FileLocator workingDirectory
Ici on envoie le message workingDirectory à la classe FileLocator, et ça me donne le chemin d'accès en cours, le dossier dans lequel l'exécution se passe.
ZnEasy getPng: 'http://pharo.org/web/files/pharo.png'
Dans ce deuxième exemple, j'envoie le message getPng:
à l'objet ZnEasy
, avec en argument une URL, l'url d'un fichier png, et ça me retourne le fichier png téléchargé.
ZnSserver startDefaultOn: 8080
Dans ce troisième exemple, j'envoie le message startDefaultOn:
à ZnSserver
, donc qui est une classe encore une fois, avec un numéro de port et ceci démarre le serveur HTTP.
Dans les 3 cas, on a une classe, on envoie un message à cette classe. Alors comment est-ce qu'on fait pour implémenter une méthode de classe?
Depuis l'IDE:
On sélectionne, le package, la classe, on appuie sur le radio-bouton Class side
pour dire qu'on veut implémenter une méthode du côté classes et non pas du côté instances (choix par défaut), et on implémente une méthode comme on ferait d'habitude.
On présente ci-dessous une erreur fréquente. Ici on souhaite définir un nouveau message à mot clé withValue:
dans la classe Counter
, pour retourner un nouveau compteur avec en valeur initiale la valeur fournie en paramètre au message withValue:
.
Donc on voudrait que
Counter withValue: 10
nous retourne un nouvel objet compteur qui commencerait à la valeur 10.
Avec l'implémentation proposée ci-dessous, on n'obtient pas le résultat attendu:
" Counter class >> withValue: anInteger " self new value: anInteger; yourself
Si on évalue cette expression on obtient la valeur Counter et pas un nouveau compteur. En fait j'obtiens la classe et pas une nouvelle instance de cette classe. Alors pourquoi cette erreur ? Quel est le problème ?
Le problème vient que par défaut, toutes les méthodes retournent self. Donc si je ne spécifie pas la valeur à retourner, la méthode va retourner self, et dans ce cas la référence vers la classe Counter.
Le code précédent est équivalent au code ci-dessous:
" Counter class >> withValue: anInteger " self new value: anInteger; yourself. ^ self
On retourne self
, dans ce cas-là, self
c'est la classe Counter
. Donc la méthode retourne la classe elle-même et pas l'instance qui a été créée juste au-dessus.
Pour corriger ce problème, il suffit d' ajouter un chapeau devant self new
.
" Counter class >> withValue: anInteger " ^ self new value: anInteger; yourself
En résumé: