Tutoriel Programmation objet immersive en Pharo proposé par l'Inria disponible à l'adresse https://mooc.pharo.org et sur la plateforme FUN-MOOC.
Présentation par , Damien Cassou membre du groupe de recherche CRIStAL de l'INRIA.
Dans cette séquence, nous allons présenter la définition de classe et méthode dans Pharo.
Ce qui est vraiment spécifique à Pharo, il n'y a pas de syntaxe particulière pour définir les méthodes et les classes. Cela se fait au niveau des outils. Donc, c'est les outils qui vont donner le contexte à la création d'une classe ou d'une méthode.
Voici le navigateur de code principal dans Pharo, c'est Nautilus (menu Tools → System Browser sous Pharo 8).
On voit dans la zone du bas, la définition de la classe Point
. On voit que la classe Point a pour superclasse la classe Object
et deux variables d'instances x
et y
.
On voit aussi en bas le nom du package dans lequel cette classe va être ajoutée.
Dans les slides, on aura ce genre d'extraits de codes pour créer une nouvelle sous-classe.
Object subclass: #Point instanceVariableNames: 'x y' classVariableNames: '' package: 'Graphics'
On voit que pour créer une classe en Pharo, on envoie un message particulier (un message à mots clés ) à la superclasse avec le nom de la sous-classe en paramètres. Donc le message subclass:instanceVariableNames:classVariableNames:package:
est un message qui est envoyé à la classe Object
, avec:
Concernant la définition de méthodes, on a dans la zone d'édition en bas encore (quand une méthode a préalablement été sélectionnée): le nom de la méthode, un commentaire et le code de la méthode.
Ci dessous le code de la méthode “factorial”
factorial "Answer the factorial of the receiver." self = 0 ifTrue: [^ 1]. self > 0 ifTrue: [^ self * (self - 1) factorial]. self error: 'Not valid for negative integers'
Et cette méthode, elle appartient à une classe. Comme vous le voyez dans la syntaxe pour définir la méthode, on n'a pas l'information sur la classe à laquelle cette méthode doit appartenir.
En fait, c'est la sélection de la classe dans le navigateur de codes qui va nous indiquer la classe à laquelle appartient la méthode.
Dans les extraits, il nous faut aussi cette information. Ce qui fait qu'on ne peut pas recopier juste le contenu de la définition d'une méthode. Il nous faut ajouter un préfixe au nom de la méthode pour indiquer à quelle classe cette méthode appartient.
Donc, on ajoute en entête du nom de la méthode, le nom de la classe à laquelle on va ajouter la méthode qu'on est en train de définir.
Integer>>factorial "Answer the factorial of the receiver." self = 0 ifTrue: [^ 1]. self > 0 ifTrue: [^ self * (self - 1) factorial]. self error: 'Not valid for negative integers'
Donc, dans le navigateur de code (System Browser), cette classe n'apparaît qu'en tant que sélection.
Donc là, on est bien en train de définir la méthode factorielle de la classe Integer. Alors, petit rappel sur les messages. Ici, on est en train de définir la méthode factorielle. On a tout un ensemble de messages binaires, donc =, >, * et - qui sont des messages binaires. On a un appel récursif à la méthode factorielle donc factorielle ici, c'est un message unaire qui est envoyé à un objet de type nombre. Et on a deux messages à mots clés: ifTrue deux fois et error. Et enfin, on a le chapeau qui est utilisé pour retourner une valeur et quitter la méthode. Alors concernant le retour, par défaut, en Pharo, toutes les méthodes retournent self donc l'objet en cours. Donc, le code qui est au-dessus est exactement similaire au code qui est en dessous. Donc, la partie return self à la fin de la méthode est complètement optionnelle. Et en général, on ne la mettra pas. Les méthodes de classes permettent d'envoyer des messages à des classes. Les classes sont des objets comme les autres. On peut envoyer des messages à des classes. Et pour définir une méthode de classe, on appuie sur le bouton “class” dans Nautilus et on définit la méthode de classe à ce moment-là. Dans les slides, on ajoutera systématiquement le mot “class” pour distinguer une méthode qui va être exécutée sur une classe plutôt que sur une instance de cette classe. Donc là, la méthode X Y, elle va être exécutée sur la classe Point et non pas sur une instance de la classe Point. Alors, ce que vous devez retenir de cette séquence: une classe est définie non pas par la syntaxe particulière, mais par un message qu'on va envoyer à sa superclasse. Les classes sont définies au sein de paquets dont les noms sont passés en paramètre du message. Toutes les méthodes sont publiques, il n'y a pas de mot-clé particulier pour indiquer qu'une méthode est publique parce que c'est le cas de toutes les méthodes. Il n'y a pas de notion de protégé, de private, etc. Par défaut, toutes les méthodes retournent le receveur, c'est-à-dire self et on peut utiliser le chapeau pour retourner autre chose que self. Et les méthodes de classe sont des méthodes comme les autres. Et pour les ajouter, il faut appuyer sur le bouton “class” avant de créer la méthode. Ceci conclut cette première semaine de cours. La semaine suivante, nous verrons plus en détails la syntaxe de Pharo, les blocks et un outil qui est l' inspecteur d'objets.