Bonjour à tous. Dans cette troisième séquence, après s'être
intéressés à l'héritage et à self et au lookup, on va s'
intéresser à super.
Dans cette séquence, nous allons nous intéresser
particulièrement à l'envoi de messages dans le cas où super est le receveur.
Alors qu'est-ce que super ?
Prenez quelques minutes pour vous poser la question et
notamment répondre à ces 2 questions.
Qu'est-ce que super représente ?
Comment se passe l'envoi de messages quand super est le receveur?
Ce que je vais vous dire ici, c'est pareil en Pharo et en Java.
Dans cet exemple-là, qui est proche des exemples vus
dans la séquence précédente, on utilise super dans une des méthodes.
On va essayer de réfléchir un peu à ce qui se passe.
Pour A new bar, aucune difficulté, même
exemple que précédemment.
Cette méthode bar est exécutée et Foo retourne 10.
Dans le cas de B new bar, on va le faire étape par
étape. On envoie le message bar à l'objet B new.
L'algorithme de lookup cherche une méthode
bar à partir de la classe de cet objet.
La méthode bar est trouvée, elle s'exécute
sur le receveur. Donc c'est cette méthode bar là qui est
exécutée sur le receveur.
Il faut maintenant que je calcule super bar, self foo et
que je fasse la somme des 2.
On peut faire self foo.
Self foo envoie le message foo à l'objet
self. Self, c'est mon B new.
Il n'y a qu'un seul foo possible, c'est celui qui est dans la classe A.
Self foo retourne 10.
Super bar : super, c'est le
receveur. Par contre, l'algorithme de lookup change en
présence du receveur super.
On v a chercher la méthode bar à partir de la super
classe de là où se trouve le mot-clé super.
Super se trouve dans la méthode bar de la classe B, donc
on va chercher une méthode bar à partir de la super
classe de B, c'est-à-dire A.
On trouve cette méthode-là et c'est cette méthode-là qui est exécutée.
Donc foo est envoyé à self.
Self, c'est toujours le même objet, c'est toujours le receveur, c'est B new.
Foo est donc envoyé sur l'objet initial et donc c'est ce
foo-là qui est exécuté qui retourne 10.
10 et 10 : 20.
Dans le cas de C new bar, on a notre C new qui est ici
qui est une instance de la classe C et on lui envoie le message bar.
Bar est cherché dans la classe de C new, c'est-à-dire C.
Il n'est pas trouvé là, il est cherché au-dessus.
Il est trouvé là, c'est donc ce bar là qui va être exécuté.
Ce bar là est la somme de 2 envois de messages.
On peut commencer par le second encore une fois, on
envoie le message foo à l'objet self.
Self, c'est toujours mon C new qui est ici.
J'envoie le message foo.
Cette méthode-là est trouvée.
50 est retourné, là j'ai 50.
Super bar, maintenant il nous manque la première partie
de l'addition de super bar.
J'envoie le message bar à super.
Super, c'est toujours le receveur mais l'algorithme de
lookup change et va chercher bar à partir de la super
classe de là où se trouve l'expression qui contient
super, c'est-à-dire la méthode bar de la classe B, c'est-à-dire
la classe B, donc on commence à chercher bar à partir de
la super classe de B, c'est-à-dire A.
Bar est trouvé ici.
Ce bar là est exécuté.
Self, c'est toujours C new, c'est toujours celui-là,
toujours le receveur et on lui envoie le message foo.
On tombe sur 50. Ici j'ai 50: 50 et 50,
100.
Dans ce slide, vous avez les détails de l'exécution de l'algorithme
pour pouvoir réviser et retravailler cet exemple.
Super référence toujours le receveur, c'est exactement
comme self ou comme this en Java.
Et pareil, super en Java, c'est comme this en Java, ça
représente toujours le receveur.
Par contre lorsqu'un message est envoyé à super, l'algorithme
de lookup change et commence à chercher une méthode à
partir de la super classe, de la classe qui contient la
méthode en train d'être exécutée dans laquelle super se trouve.
Self et super ont donc une différence fondamentale: self
est dynamique tandis que super est statique.
Qu'est-ce que je veux dire par là ?
Je veux dire que quand foo est envoyé à self, le
développeur n'a aucune idée de la méthode foo qui va être exécutée.
Ça peut être le foo qui se trouve dans la même classe,
dans une sous-classe existante ou dans une sous-classe
qui sera créée par un autre développeur avant l'exécution du programme.
Donc lorsque le développeur de la méthode bar écrit self
foo, il n'a aucune idée de la méthode foo qui va être exécutée.
C'est particulièrement pratique, ça veut dire que les
développeurs peuvent créer de nouvelles sous-classes pour
changer le comportement de la classe A.
Super, à l'inverse, est statique.
Lorsque le développeur écrit "Super foo",
il sait quelle est la méthode foo qui sera exécutée
lorsque le programme sera exécuté.
Donc en écrivant ça, il sait que ça sera cette méthode
foo-là qui sera exécutée.
Toujours. Super est statique, à la compilation on sait
quelle méthode sera exécutée.
Malheureusement, certains livres se trompent dans la
définition de super et donnent des définitions qui n'ont pas de sens.
Voici une définition qu'on a trouvée dans un livre et
dans cette définition-là, on nous dit que super cherche
la méthode. Donc l'algorithme de lookup quand il voit
super va chercher la méthode à partir de la super classe du receveur.
Donc la super classe de la classe du receveur.
En fait cette définition est fausse.
Si on prend l'exemple ci-dessous, si on prend comme
receveur AC, sa classe c'est C.
La super classe du receveur c'est donc B.
Et si ici, j'exécute cette partie-là
avec la définition qui est donnée plus haut et qui est
fausse, on enverrait le message foo
à super, et la méthode foo qui serait exécutée, c'est la
méthode foo qui se trouve dans la super classe de la
classe du receveur, c'est-à-dire cette méthode foo là qui
exécuterait ça, qui enverrait le message foo à super, qui
exécuterait ça, et cetera. Et donc on voit ici qu'on a
une boucle infinie, c'est bien que la définition est
fausse parce que dans la pratique cet exemple n'est pas une boucle infinie.
Cet exemple fonctionne parfaitement.
Et donc la définition est juste fausse.
Ce que de vous devez retenir: Self représente toujours
le receveur ainsi que Super.
Et c'est pareil en Java, This et Super représentent toujours le receveur.
Par contre, Super change l'algorithme de lookup.
L'algorithme de lookup va chercher une méthode
correspondante à partir de la super classe de la classe
qui contient la méthode, qui contient le mot-clé Super.
Les envois de messages à Self sont dynamiques, et on peut
s'en servir en tant que développeur pour étendre le
comportement d'une classe existante en faisant une
sous-classe, qui redéfinit une méthode.