Fun avec les messages
By Hilaire Fernandes on Sunday, April 19 2009, 10:52 - Chroniques Smalltalk - Permalink
En programmation orientée objet Smalltalk, nous n'appelons pas des méthodes mais nous envoyons des messages à des objets pour leur demander poliment d'exécuter un traitement. L'objet recevant le message décide alors de la méthode à utiliser pour répondre à cet appel.
Un message est simplement un nom et une éventuelle liste d'arguments. A partir des messages, le programmeur construit des petits phrases (les badinages Smalltalk). Pour ce faire il existe trois types de message : les messages unaire, binaire et à mot clé.
Message unaire
Le message unaire est le plus simple, il est envoyé à un objet sans argument, l'écriture du message suit directement celle de l'objet (le receveur). Par exemple, pour demander à un nombre son cosinus, nous lui envoyons simplement le message cos :
0.5 cos --> 0.877582561890373 ( 1 + 2i ) cos --> 2.032723007019665 - 3.0518977991518 i #( 0 0.5 ) cos --> #(1.0 0.877582561890373)
Le même message est envoyé à des objets (les receveurs) de différentes natures (respectivement instances des classes Float, Complex et Array). A la réception du message, le receveur décide du traitement à appliquer.
Dans une chronique précédente, nous avions introduit les objets durée que nous pouvons créer en envoyant le message unaire seconds à un nombre :
90 seconds --> 0:00:01:30
Message binaire
Un message binaire est envoyé à un objet avec un seul argument. L'écriture du message suit celle du receveur suivi d'un objet, l'argument. Par exemple, pour ajouter deux nombres, nous utilisons le message binaire + :
5 + 2 --> 7
L'addition n'est donc pas un opérateur défini dans le langage, c'est une méthode définie dans les classes souhaitant répondre à ce message. Ainsi des objets comme des durées répondent à ce message :
90 seconds + 30 seconds --> 0:00:02:00
Dans l'expression ci-dessus, il y a trois messages. Il faut savoir que les messages unaires sont prioritaires sur les messages binaires, l'exécution se fait donc dans l'ordre suivant :
90 seconds-->Duration 0:00:01:3030 seconds-->Duration 0:00:00:30- le message
+est envoyé à l'instanceDuration 0:00:01:30avec comme argument l'instanceDuration 0:00:00:30
Les objets couleurs répondent aussi à ce message pour mélanger des couleurs :
Color red + Color blue --> Color magenta
Quelle est la priorité lorsque une expression comporte plusieurs messages binaires ? En cas d'égalité de priorité, l'exécution se fait de gauche à droite. Ainsi
4 + 5 * 4 --> 36
est arithmétiquement équivalent à ( 4 + 5 ) * 4. Puisque les opérateurs n'existent pas en tant que tel dans le langage Smalltalk, il n'y a pas non plus de notion de priorité des opérateurs. Pour obtenir la priorité souhaitée, utiliser des parenthèses :
4 + ( 5 * 4 ) --> 24
Message à mot clé
Un message à mot clé est envoyé à un receveur avec plusieurs arguments, les arguments sont intercalés entre les différentes composantes du message à mot clé. Par exemple, pour définir une couleur à partir de ses composantes rouge, verte et bleue nous envoyons le message r:g:b: à l'objet Color :
Color r: 1 g: 0 b: 0 --> Color red Point x: 5 y: 0.5 --> 5@0.5
La deuxième expression définit un point de coordonnées (5 ; 0.5) en utilisant le message x:y: envoyé à la classe Point.
Noter qu'un point se définit aussi avec le message binaire @ envoyé à un nombre avec un autre nombre comme argument.
Le message à mot clé est de priorité inférieure à celle des messages unaire et binaire. L'ordre de priorité des messages est donc :
message unaire > message binaire > message à mot clé
Pour définir notre point, nous pouvons donc écrire :
Point x: 5 y: 1 / 2
mais les parenthèses sont nécessaires lorsque nous utilisons le message @ pour définir notre point ;
5 @ ( 1 / 2 )
Sans les parenthèses l'expression aura un autre sens, explicitée ici avec les parenthèses :
( 5 @ 1 ) / 2
C'est une expression valide car un point comprend le message /, le résultat est le point ( 5 / 2) @ (1 / 2)
Exemple de composition
Pour en revenir au badinage, voici une recette d'un quatre quarts écrite en Smalltalk :
preparation := Recette new. preparation ajoute: 200 g de: Sucre. preparation ajoute: 200 g de: Farine. preparation ajoute: 20 g de: Levure. preparation ajoute: 3 de: Oeuf. preparation melange. preparation cuisson: 45 minutes
Les arguments Sucre, Farine, Levure et Oeuf sont des classes manipulables comme tout autre objet. En Smalltalk les classes sont des objets de première classe.
Conclusion
Notre rapide panorama des messages s'achève ici. Pour compléter cette mise en bouche, je vous invite à la lecture du livre Squeak par l'exemple.
That's all folks!




Comments
sympa
Par contre, pour l'exemple final par contre, tu triches un peu 
g n'étant pas un message de Number... 200 g donnera une erreur.
Peut-être:
...
preparation ajoute: (Sucre quantite: '200 g')
Ou
preparation ajoute: (Sucre quantiteEnGramme: 200)
C'est sur que ca n'est pas aussi joli par contre... mais c'est toujours mieux que du Java
@+
Arg !
ces informaticiens...
du quatre-quart qui ne fait que trois quarts....
comme dis ma grand-mère: avec du beurre tout est meilleur!
pour en revenir au sujet: en SmallTalk j'ai pris l'habitude d'envoyer mes arguments aux methodes sous forme de tableaux. ça evite des noms de méthode trop long quand il y a beaucoup d'arguments. est-ce une mauvaise habitude?
Cédrick,
Tu as raison la méthode g n'existe pas dans la classe Number. L'exemple illustre ce qu'il est possible d'écrire.
Mais il est aisé, d'une part, de définir une classe Weight, et d'autre part, de définir une méthode g dans la classe Number pour que celle-ci retourne une masse (instance de Weight) avec le receveur comme quantité. En fait exactement à l'image de la classe Duration et les messages 'seconds', 'minutes', 'hours',... de la classe Number.
Julien,
Pour le tableau en argument, tu perds le sens que tu peux avoir avec les messages à mot clé. La relecture du code quelques semaines, voire quelques mois après peut être moins aisée.
Mais bon ça dépend aussi de l'usage et du contexte.