Outils pour utilisateurs

Outils du site


cours:informatique:dev:programmation_objet_pharo:040_methode_vs_message

Méthode versus message

Tutoriel Programmation objet immersive en Pharo proposé par l'inria disponible à l'adresse https://mooc.pharo.org et sur la plateforme FUN-MOOC.

Transcription de la vidéo

Cours présenté par Stéphane Ducasse, directeur de recherche à l'Inria.

On a vu précédemment qu'une méthode, c'est une séquence nommée d'instructions. Là, j'ai une méthode que j'ai imaginée pour faire des crêpes. En fait, une méthode, c'est comme une recette de cuisine. Je vais avoir une suite d'instructions à suivre et à exécuter. Pour faire des crêpes, je vais mettre des œufs, du lait, du sucre et de la farine et j'obtiens des crêpes. C'est ma recette de cuisine pour faire les crêpes. C'est aussi la méthode makeCrepes. C'est la même chose.

Toutes les instances d'une classe vont partager le même comportement. En fait, quand je vais envoyer un message à une instance, je vais chercher dans la classe. La classe contient toutes les méthodes pour ces instances. Le système recherche la méthode qui est associée au message dans la classe et l'exécute sur le receveur du message.

La méthode définit le comportement. C'est une suite d'instructions. Elle a un nom qui est souvent en relation avec le message. En Pharo, c'est le nom qui déterminera la méthode qu'on devra exécuter. Dans d'autres langages, c'est un peu différent mais c'est le même principe. La méthode va pouvoir accéder à l'état propre de l'objet. C'est une particularité, alors que le message est extérieur.

J'envoie un message à un objet. Je ne me préoccupe pas des valeurs. Je n'ai pas accès aux valeurs internes de l'objet. C'est la méthode qui, elle, est proche des données. On a vu qu'une méthode, c'est comment on va faire une opération. Comment on va répondre à un message. Et un message, c'est le quoi ( l'ordre). Les messages déterminent quoi faire et les méthodes spécifient comment.

Si on regarde les différences qu'on a, le message va être extérieur à l'objet. La méthode va être vraiment intérieure. Elle pourra accéder aux données. Le message est plus abstrait, dans ce sens-là et moins opérationnel. On veut que la chose soit faite et non pas savoir comment elle est faite. Ça a une influence, après, sur l'encapsulation. Je reviendrai plus tard là-dessus.

Le message, lui, va juste être : “J'envoie un message à un objet avec les paramètres et je m'attends à ce que ça soit exécuté. J'attends que l'objet réalise ce pour quoi je l'ai invoqué.” Ce qu'il faut voir, c'est que les méthodes sont recherchées dynamiquement. Là, j'ai deux exemples d'illustration. Je vous ai montré l'exemple dans un cours précédent avec les animaux. Je vais envoyer le même message à différentes instances d'objets qui sont d'instances de différentes classes. Quand j'envoie le message “angry” à un chien, je cherche dans la classe chien. Quand j'envoie un message “angry” à un chat, je vais dans la classe chat. J'ai la même chose, par exemple, sur les formes mathématiques. Quand je demande quelle est l'aire à un rectangle, je m'attends à ce que la classe Rectangle implémente cette fonctionnalité-là et me dise que c'est la longueur multipliée par la largeur. Pour le cercle, je voudrais bien avoir Pi R² et ce genre de choses. On voit bien que les méthodes vont dépendre des instances… Les méthodes exécutées vont dépendre des instances qui sont receveurs du message. Sur cet exemple-là, on pourrait avoir une liste qui contient des formes, à la fois des rectangles, des carrés et des cercles et on pourrait faire la somme des aires en envoyant le message “aire” à chacun des objets de cette liste. Je n'ai pas à distinguer… “J'ai un rectangle ? J'ai un carré ou un cercle ?” J'ai simplement à envoyer le message à chaque forme en lui disant : “Calcule ton aire” pour que cette aire soit calculée. C'est le pouvoir de la liaison tardive (late binding).

La liaison tardive, c'est l'idée que la méthode qui sera exécutée sera déterminée lors de l'exécution, que la bonne méthode sera exécutée par rapport à ça. C'est la différence entre la programmation procédurale et la programmation objet. En programmation objet, on n'écrira pas de test. On va juste donner des ordres. Et le mécanisme de sélection des méthodes va se réaliser automatiquement et exécuter la bonne méthode, donc celle qui correspond au receveur. Ce mécanisme s'appelle la liaison tardive. La liaison tardive, “late binding” en anglais, qu'est-ce que ça signifie ?

Lors de la compilation, je ne connais pas le code qui va être exécuté. Je sais que je vais devoir rechercher la méthode lors de l'exécution. Des techniques d'optimisation font que la deuxième fois qu'on cherche la même chose, on la trouve plus rapidement, etc., mais la liaison tardive est un mécanisme fondateur et fondamental de la programmation objet.

A propos de l'encapsulation des données, je vous ai dit qu'un objet a des données qui lui sont propres et des méthodes qui sont partagées par la classe. Conceptuellement, on peut penser qu'un objet est un patatoïde avec des données, au milieu, des méthodes et des messages au dehors. On envoit des messages pour exécuter des méthodes. Ces méthodes ont accès à des données.

À quoi sert cette distinction ? En tant que client, j'ignore comment c'est implémenté à l'intérieur, comment son traitées les données. L'encapsulation va me permettre de changer et d'avoir des objets qui me proposent la même interface, le même message, mais qui ont des implémentations différentes.

Là, par exemple, on a deux implémentations différentes de comment on calcule l'aire d'un rectangle. D'un point de vue de client, ça ne m'intéresse pas. L'information n'est pas intéressante pour moi. Je veux, lorsque j'envoie mon message “aire”, recevoir la bonne aire et qu'elle soit bien calculée. Maintenant, je peux avoir deux objets qui me proposent une méthode aire et qu'elles soient implémentées différemment. Ça me permettra de faire évoluer mes applications dans le temps sans avoir à tout réécrire.

Il se trouve que là, tout le code client qui était basé sur la méthode aire est réutilisable. Que je mette un objet dont l'implémentation est celle du haut ou celle du bas, qui sont deux implémentations différentes, ce n'est pas grave. Ça signifie que le code client va continuer à marcher. Donc, il pourra évoluer sur un plus long terme et je n'ai pas à recompiler tout le système.

L'encapsulation des données est très importante, car elle permettra une pérennisation, une évolution et de cacher des détails qui ne sont pas opportuns. Ce sont de très bonnes propriétés de la programmation objet.

En résumé, je vous ai montré que les méthodes sont des séquences d'instructions. Les messages représentent des ordres. À partir de ces ordres, les méthodes seront exécutées. Les méthodes sont partagées entre toutes les instances des classes. On peut avoir différentes méthodes ayant le même nom. Ce n'est pas un problème entre différentes classes. Et je peux envoyer le même message à différents objets qui exécuteront des méthodes différentes. À cela s'ajoute l'encapsulation apportant une distance par rapport aux données et à la prise de décision de comment j'ai encodé mon calcul qui fait que je pourrai faire évoluer mes objets sans impacter mes clients (utilisateurs de l'objet). Toutes ces propriétés sont fondamentales et liées à la liaison dynamique.

⌂ Retour au sommaire

cours/informatique/dev/programmation_objet_pharo/040_methode_vs_message.txt · Dernière modification : 2022/06/27 20:00 de yoann