WEBVTT

00:00:00.580 --> 00:00:02.870 align:middle
Bonjour. Dans cette
séquence, nous faisons suite à la

00:00:03.070 --> 00:00:05.450 align:middle
séquence précédente dans
laquelle je disais que les

00:00:05.650 --> 00:00:07.010 align:middle
petites méthodes,
c'était vraiment bien.

00:00:07.530 --> 00:00:09.000 align:middle
Ici, je vais vous
montrer des exemples.

00:00:09.770 --> 00:00:13.480 align:middle
Pour revenir rapidement sur
la séquence précédente, un

00:00:13.680 --> 00:00:17.540 align:middle
envoi de messages c'est un
choix masqué parce qu'il peut

00:00:17.740 --> 00:00:21.560 align:middle
y avoir plusieurs implémentations
possibles qui vont être appelées.

00:00:22.150 --> 00:00:25.460 align:middle
Pharo choisit laquelle en
fonction du receveur du message.

00:00:26.570 --> 00:00:28.280 align:middle
C'est la hiérarchie de
 classes qui définit les choix:

00:00:28.480 --> 00:00:29.830 align:middle
plus on a de
 classes, plus on a de choix.

00:00:31.030 --> 00:00:33.050 align:middle
Et on peut ajouter de
nouveaux choix facilement en créant

00:00:33.250 --> 00:00:34.010 align:middle
de nouvelles sous-classes.

00:00:35.870 --> 00:00:40.130 align:middle
Les sous-classes peuvent redéfinir et
raffiner le code de leur super classe.

00:00:42.120 --> 00:00:45.700 align:middle
En fait, envoyer un message,
c'est laisser la possibilité

00:00:46.360 --> 00:00:49.230 align:middle
à des sous-classes de
changer le comportement.

00:00:50.720 --> 00:00:53.680 align:middle
On va s'intéresser au design
pattern Template Method, que

00:00:53.880 --> 00:00:56.500 align:middle
vous trouverez dans le
livre de "Design pattern".

00:00:57.730 --> 00:01:00.140 align:middle
Une template Method c'est quoi ?

00:01:00.340 --> 00:01:03.040 align:middle
C'est un squelette, ça
définit globalement le

00:01:03.240 --> 00:01:08.160 align:middle
comportement d'un
algorithme, par exemple avec des trous

00:01:08.360 --> 00:01:12.080 align:middle
à l'intérieur et ces trous vont
pouvoir être redéfinis par les sous-classes.

00:01:13.940 --> 00:01:17.840 align:middle
Là, j'ai un exemple
d'algorithme qui fait quelque chose

00:01:18.040 --> 00:01:21.830 align:middle
mais on ne sait pas trop
quoi, qui ensuite va faire

00:01:22.030 --> 00:01:24.470 align:middle
quelque chose qui va être
dans une méthode hookMethod1,

00:01:25.810 --> 00:01:29.030 align:middle
puis autre chose, puis quelque
chose qui se trouve dans hookMethod2.

00:01:29.230 --> 00:01:34.130 align:middle
hookMethod1 et 2
puisque ce sont des méthodes à

00:01:34.330 --> 00:01:36.410 align:middle
part entière, elles vont pouvoir
être redéfinies dans les sous-classes.

00:01:37.890 --> 00:01:40.730 align:middle
Il y a 2 possibilités
pour hookMethod1 et 2.

00:01:41.850 --> 00:01:46.480 align:middle
Ces méthodes peuvent avoir

00:01:46.820 --> 00:01:49.530 align:middle
une implémentation par défaut ou pas.

00:01:50.290 --> 00:01:53.590 align:middle
Ici, on peut dire que
hook1 a une implémentation par

00:01:53.790 --> 00:01:56.430 align:middle
défaut, c'est-à-dire que
si la sous-classe ne propose

00:01:56.630 --> 00:02:00.480 align:middle
rien hook1 a une
implémentation par défaut qui

00:02:02.410 --> 00:02:07.290 align:middle
va marcher. Ou
alors, on peut dire que

00:02:07.490 --> 00:02:10.060 align:middle
hookMethod2 n'a pas
d'implémentation et qu'il faut

00:02:10.260 --> 00:02:12.230 align:middle
absolument que la
sous-classe définisse un comportement.

00:02:12.430 --> 00:02:15.470 align:middle
Là, vous avez le choix en
tant que concepteur de la

00:02:15.670 --> 00:02:18.310 align:middle
 classe, soit de fournir
une implémentation, un

00:02:18.510 --> 00:02:19.610 align:middle
comportement par défaut, soit non.

00:02:20.710 --> 00:02:23.090 align:middle
On va prendre un premier
exemple, l'exemple de printString.

00:02:24.430 --> 00:02:27.010 align:middle
L'idée, c'est que si
j'envoie le message printString à un

00:02:27.210 --> 00:02:30.560 align:middle
objet, j'obtiens une chaîne de
caractères qui représente cet objet.

00:02:31.370 --> 00:02:35.640 align:middle
Là, j'ai un délai. Je crée un délai

00:02:36.650 --> 00:02:40.590 align:middle
de 10 secondes. Si j'envoie
le message printString à ce

00:02:40.790 --> 00:02:45.460 align:middle
delay là, je vois'a
delay'et entre parenthèses, la

00:02:45.660 --> 00:02:47.260 align:middle
valeur en millisecondes du delay.

00:02:48.470 --> 00:02:51.500 align:middle
La méthode printString est
implémentée dans la classe

00:02:51.700 --> 00:02:54.860 align:middle
objects de cette
façon-là. En fait, elle envoie le

00:02:55.060 --> 00:02:57.560 align:middle
message printString
LimitedTo. Cette implémentation-là

00:02:57.760 --> 00:03:02.450 align:middle
récupère une chaîne de
caractères qui représente

00:03:03.230 --> 00:03:07.710 align:middle
l'objet, et ensuite
si cette chaîne de

00:03:07.910 --> 00:03:12.110 align:middle
caractères-là est trop
grande on peut la couper à une

00:03:12.310 --> 00:03:16.780 align:middle
certaine valeur, la limite,
et concaténer à la fin point

00:03:17.000 --> 00:03:19.520 align:middle
point point etc. pour dire que la
chaîne de caractères n'est pas terminée.

00:03:20.950 --> 00:03:23.070 align:middle
Là, l'important ici c'est de voir que

00:03:23.270 --> 00:03:27.920 align:middle
printStringLimitedTo envoie
le message printOn à self.

00:03:28.500 --> 00:03:33.060 align:middle
C'est cette méthode-là qui va être
redéfinie dans les sous-classes ou pas.

00:03:34.300 --> 00:03:39.000 align:middle
Si je regarde ce que
retourne printString pour un

00:03:39.200 --> 00:03:43.660 align:middle
nœud et pour une pomme, là
Node new retourne a Node.

00:03:44.340 --> 00:03:48.330 align:middle
Ça, c'est le
printString de la classe Node.

00:03:49.220 --> 00:03:53.190 align:middle
Et là an Apple, c'est le
prinString de la classe Apple.

00:03:53.940 --> 00:03:56.530 align:middle
On voit que ce
comportement est le comportement par

00:03:56.730 --> 00:03:59.180 align:middle
défaut et il est
implémenté dans la classe objects.

00:04:00.370 --> 00:04:03.300 align:middle
Le comportement par défaut
du printString pour n'importe

00:04:03.500 --> 00:04:05.540 align:middle
quel objet, c'est 1,

00:04:08.610 --> 00:04:12.400 align:middle
récupérer le nombre de la
 classe, donc là Node et Apple,

00:04:13.180 --> 00:04:16.330 align:middle
et ensuite si ce nom de
 classe commence par une voyelle

00:04:17.740 --> 00:04:21.430 align:middle
alors on va préfixer par
an, et si ça commence par une

00:04:21.630 --> 00:04:22.860 align:middle
consonne on va préfixer par a.

00:04:23.170 --> 00:04:25.060 align:middle
C'est ça qui nous permet
d'avoir "a node" et "an apple.

00:04:25.260 --> 00:04:29.910 align:middle
" C'est l'implémentation par

00:04:30.110 --> 00:04:33.840 align:middle
défaut et il est possible de
changer ce comportement par

00:04:34.040 --> 00:04:35.930 align:middle
défaut en ré implémentant printOn.

00:04:37.240 --> 00:04:41.360 align:middle
Donc là pour un delay on
voit que le print string d'un

00:04:41.560 --> 00:04:45.820 align:middle
delay, ça commence par ce
que retourne print on par

00:04:46.020 --> 00:04:49.490 align:middle
défaut, c'est-à-dire a
délai, mais qu'ensuite on ajoute

00:04:50.230 --> 00:04:52.220 align:middle
entre parenthèses le
delay en millisecondes.

00:04:52.950 --> 00:04:55.710 align:middle
C'est exactement ce que fait
l'implémentation de la méthode printOn.

00:04:57.000 --> 00:04:59.680 align:middle
Elle commence par
demander à la super classe le

00:04:59.880 --> 00:05:04.310 align:middle
printString par défaut,
et ensuite ça ajoute la

00:05:04.510 --> 00:05:07.230 align:middle
parenthèse à un nombre
de millisecondes préfixé

00:05:09.480 --> 00:05:10.520 align:middle
ainsi que la parenthèse fermante.

00:05:11.890 --> 00:05:14.750 align:middle
Là nous avons vu du raffinement.

00:05:15.160 --> 00:05:19.660 align:middle
La classe delay raffine
l'implémentation de la méthode

00:05:19.860 --> 00:05:21.360 align:middle
print on de la classe objects.

00:05:21.700 --> 00:05:24.810 align:middle
Et une classe peut aussi
redéfinir complètement le comportement.

00:05:26.010 --> 00:05:30.010 align:middle
C'est le cas pour les
booléens par exemple.

00:05:30.210 --> 00:05:35.140 align:middle
Si j'affiche false,
ça me retourne false et

00:05:35.340 --> 00:05:39.040 align:middle
donc on n'a pas a
false, on a juste false.

00:05:39.640 --> 00:05:43.090 align:middle
Pour ça, on envoie juste la
chaîne de caractères false

00:05:43.670 --> 00:05:45.300 align:middle
dans le stream passé
en paramètre à printOn.

00:05:46.510 --> 00:05:47.600 align:middle
C'est une redéfinition complète.

00:05:47.800 --> 00:05:51.290 align:middle
Un autre exemple de redéfinition
complète, c'est pour les intervalles.

00:05:52.210 --> 00:05:54.510 align:middle
Un intervalle définit un
ensemble de valeurs entre une

00:05:54.710 --> 00:05:56.430 align:middle
valeur minimum et une valeur maximum.

00:05:58.200 --> 00:06:02.010 align:middle
L'intervalle 1 à 100 s'affiche
parenthèse 1 to: 100 parenthèse.

00:06:04.450 --> 00:06:09.290 align:middle
L'intervalle 1 à 100
par "pas de 3", donc 1,

00:06:09.490 --> 00:06:14.410 align:middle
4, et caetera, affiche la
même chose mais avec le pas en

00:06:15.780 --> 00:06:18.740 align:middle
plus. Comment est-ce
que c'est implémenté?

00:06:19.110 --> 00:06:23.550 align:middle
La classe Interval
redéfinit la méthode Print on et

00:06:23.750 --> 00:06:26.000 align:middle
envoie différents messages
au aStream passé en paramètre.

00:06:26.760 --> 00:06:30.270 align:middle
Déjà on affiche une parenthèse,
c'est la parenthèse qui s'affiche

00:06:30.470 --> 00:06:34.480 align:middle
ici et ici, puis on affiche
la valeur initiale enfin le

00:06:34.680 --> 00:06:39.180 align:middle
début de l'intervalle,
c'est-à-dire 1 et 1 qui se trouve ici.

00:06:39.760 --> 00:06:41.110 align:middle
Puis on affiche 2.

00:06:44.710 --> 00:06:46.180 align:middle
Puis on affiche la valeur finale.

00:06:46.380 --> 00:06:50.880 align:middle
C'est 100 et 100. Enfin, s'il y a un

00:06:51.080 --> 00:06:55.140 align:middle
pas différent de 1 qui
est le défaut, on affiche

00:06:56.150 --> 00:06:59.550 align:middle
le pas et

00:07:01.200 --> 00:07:05.340 align:middle
à la fin on met la parenthèse.

00:07:06.050 --> 00:07:09.080 align:middle
Donc on a vu que printString
utilisait le design pattern

00:07:09.280 --> 00:07:12.550 align:middle
template method pour que les
 classes puissent implémenter

00:07:12.750 --> 00:07:14.800 align:middle
leurs propres
représentations textuelles.

00:07:15.000 --> 00:07:19.160 align:middle
On va avoir un autre
exemple sous la forme du message

00:07:19.360 --> 00:07:24.300 align:middle
copie, qui permet de
prendre un objet et

00:07:24.500 --> 00:07:25.810 align:middle
d'en créer un clone.

00:07:27.720 --> 00:07:31.630 align:middle
La copie d'objets c'est
complexe et il peut y avoir

00:07:31.850 --> 00:07:35.630 align:middle
différentes stratégies, donc
chaque classe peut décider à

00:07:35.830 --> 00:07:39.110 align:middle
quoi doit ressembler une
copie d'une de ses instances.

00:07:40.210 --> 00:07:42.720 align:middle
Il existe une solution
simple sous la forme d'un template

00:07:42.920 --> 00:07:46.450 align:middle
method qui met en jeu les
méthodes copy et postCopy.

00:07:47.000 --> 00:07:48.710 align:middle
Copy, c'est le template method.

00:07:48.910 --> 00:07:50.560 align:middle
Postcopy, c'est le hook.

00:07:52.020 --> 00:07:55.080 align:middle
Dans la classe objects, il y
a une méthode copy, je vous

00:07:55.280 --> 00:07:59.300 align:middle
laisse lire le
commentaire, et cette méthode-là

00:08:01.300 --> 00:08:05.950 align:middle
envoie shallowCopy
comme message à self, puis

00:08:06.740 --> 00:08:08.550 align:middle
postCopy sur le résultat.

00:08:09.160 --> 00:08:14.080 align:middle
ShallowCopy, ça crée
un nouvel objet qui

00:08:14.280 --> 00:08:17.820 align:middle
partage toutes les variables
d'instances avec l'objet de base.

00:08:18.610 --> 00:08:22.090 align:middle
On a 2 objets et toutes leurs
variables d'instances sont les mêmes.

00:08:22.300 --> 00:08:24.280 align:middle
Donc si je modifie la
variable d'instance d'un des

00:08:24.480 --> 00:08:26.010 align:middle
objets, je modifie la
variable d'instance de l'autre objet.

00:08:27.670 --> 00:08:31.940 align:middle
Ça, c'est le comportement par défaut

00:08:34.680 --> 00:08:35.440 align:middle
de shallowCopy.

00:08:35.950 --> 00:08:40.140 align:middle
Maintenant suivant ce que
va faire postCopy, ce partage

00:08:40.340 --> 00:08:41.610 align:middle
va se faire ou ne va pas se faire.

00:08:41.810 --> 00:08:44.230 align:middle
Si postCopy est vide, toutes
les variables sont partagées

00:08:44.480 --> 00:08:47.470 align:middle
et les classes peuvent
décider de mettre différentes

00:08:47.670 --> 00:08:50.070 align:middle
choses dans postCopy, pour
partager certaines variables

00:08:50.270 --> 00:08:51.880 align:middle
et pas d'autres ou ne
partager aucune variable.

00:08:53.080 --> 00:08:57.480 align:middle
Par défaut postCopy partage
tout, donc ça retourne juste

00:08:58.130 --> 00:09:02.750 align:middle
l'objet en cours. Mais on peut
tout à fait imaginer d'autres

00:09:02.950 --> 00:09:04.000 align:middle
implémentations de postCopy.

00:09:04.180 --> 00:09:08.710 align:middle
Là, par exemple dans la
 classe Bag, Bag c'est un type de

00:09:08.910 --> 00:09:13.110 align:middle
collection, et sa méthode de
post Copy copie son contenu.

00:09:14.750 --> 00:09:18.160 align:middle
Un Bag a une variable
d'instances contents et les

00:09:18.750 --> 00:09:21.720 align:middle
concepteurs de la classe
Bag ont décidé que lorsqu'on

00:09:21.920 --> 00:09:25.520 align:middle
fait une copie d'un Bag,
on ne veut pas partager la

00:09:25.720 --> 00:09:27.690 align:middle
variable contents, on veut 2
variables contents séparées.

00:09:28.330 --> 00:09:29.840 align:middle
Au début, elles auront la
même valeur mais si j'en

00:09:30.040 --> 00:09:31.490 align:middle
modifie une, je ne
modifierais pas l'autre.

00:09:33.740 --> 00:09:37.170 align:middle
Là, l'idée c'est que
postCopy c'est un message qui est

00:09:37.370 --> 00:09:40.610 align:middle
envoyé à la copie, donc au
nouvel objet, qui partage

00:09:43.370 --> 00:09:45.810 align:middle
toutes les variables
d'instances, et si on ne veut pas

00:09:46.010 --> 00:09:48.410 align:middle
les partager il suffit
d'en créer de nouvelles et de

00:09:48.610 --> 00:09:49.730 align:middle
décider quelle valeur on met dedans.

00:09:50.820 --> 00:09:54.000 align:middle
Là, dans ma variable
contents, je vais mettre une copie

00:09:54.200 --> 00:09:56.380 align:middle
du contents d'origine.
Comme ça je ne partage plus le

00:09:56.580 --> 00:09:59.250 align:middle
contents, chaque copie de
mon Bag a son propre contents.

00:10:00.700 --> 00:10:03.220 align:middle
Pour le dictionnaire, on
veut aller encore plus loin.

00:10:03.720 --> 00:10:06.010 align:middle
Un dictionnaire en fait
c'est une collection de paires

00:10:06.210 --> 00:10:08.570 align:middle
clefs valeurs, donc une
collection d'associations.

00:10:09.260 --> 00:10:13.680 align:middle
Et si on copie un

00:10:13.880 --> 00:10:16.050 align:middle
dictionnaire, on veut
copier la collection.

00:10:16.250 --> 00:10:18.840 align:middle
Donc chaque dictionnaire va
avoir sa propre collection de paires.

00:10:19.060 --> 00:10:21.070 align:middle
Mais on veut aussi que
chaque paire soit différente de

00:10:21.270 --> 00:10:23.860 align:middle
façon à ce que si je
modifie une paire d'un côté, ça ne

00:10:24.060 --> 00:10:26.280 align:middle
va pas modifier une
paire de l'autre côté.

00:10:27.200 --> 00:10:31.270 align:middle
Pour ça, je copie le
tableau mais je copie aussi chaque

00:10:31.470 --> 00:10:34.510 align:middle
paire à l'intérieur et c'est
exactement ce qui se passe là.

00:10:35.220 --> 00:10:37.130 align:middle
En conclusion, le design
pattern template method est

00:10:37.330 --> 00:10:40.530 align:middle
vraiment très très
fréquent. En fait, c'est un signe de

00:10:40.730 --> 00:10:43.080 align:middle
bonne conception et si vous
faites de la bonne conception

00:10:43.280 --> 00:10:45.250 align:middle
objet, vous allez vous
retrouver avec des templates

00:10:45.450 --> 00:10:48.140 align:middle
methods partout, c'est parfaitement
normal et c'est même une bonne chose.

00:10:49.340 --> 00:10:53.730 align:middle
N'hésitez pas à vous
en servir, ça permet aux

00:10:53.930 --> 00:10:57.350 align:middle
sous-classes de définir du
comportement et de modifier en

00:10:57.550 --> 00:10:59.380 align:middle
partie le
comportement de la super classe.

