1 00:00:06,520 --> 00:00:11,160 Bonjour. Pour ce cours, on va parler essentiellement de 2 00:00:11,360 --> 00:00:15,460 conception objet et on va regarder ce qui est l'essence 3 00:00:15,730 --> 00:00:19,400 du dispatch ou de la liaison tardive dans le langage à 4 00:00:20,830 --> 00:00:25,740 objet. Ce cours prend Pharo comme exemple et c' 5 00:00:25,940 --> 00:00:28,150 est agréable de voir que Pharo est bien implémenté, mais 6 00:00:28,350 --> 00:00:31,670 il y a une forte généralisation possible qu'on verra dans le cours qui suit. 7 00:00:32,220 --> 00:00:33,000 Commençons. 8 00:00:35,000 --> 00:00:39,560 Si on regarde les booléens, dans Pharo, c'est 9 00:00:40,890 --> 00:00:43,000 tout ce qu'il y a de plus basique. 10 00:00:43,180 --> 00:00:47,000 Vous avez des opérateurs booléens qui sont gloutons comme &, |, not. 11 00:00:47,930 --> 00:00:50,570 Vous avez des opérateurs paresseux comme or: qui vont 12 00:00:50,770 --> 00:00:52,220 évaluer leurs arguments que si nécessaire. 13 00:00:52,420 --> 00:00:57,010 Vous avez aussi les conditions, ce qu'on verra dans un autre cours. 14 00:00:58,580 --> 00:01:02,210 C'est bien implémenté, mais il n'y a rien de fantastique ou de spécifique. 15 00:01:03,570 --> 00:01:06,000 La semaine dernière, je vous avais demandé de faire un exercice. 16 00:01:06,200 --> 00:01:08,820 Je vous avais posé trois questions, je vous demandais 17 00:01:09,020 --> 00:01:11,140 comment est-ce qu'on implémente not; comment est-ce qu'on 18 00:01:11,340 --> 00:01:13,930 implémente |, et ça, c'est la question la plus 19 00:01:14,130 --> 00:01:15,640 importante, pourquoi est-ce que je posais ces questions? 20 00:01:16,830 --> 00:01:19,290 On va d'abord répondre aux 2 premières et puis dans la 21 00:01:19,490 --> 00:01:22,330 séance qui suit, je répondrai à 22 00:01:26,000 --> 00:01:27,150 la question trois. 23 00:01:27,350 --> 00:01:28,820 L'exercice, c'était vraiment, j'ai false. 24 00:01:29,020 --> 00:01:32,890 Si j'envoie le message not à false, ça va me rendre true. 25 00:01:33,090 --> 00:01:35,170 Si j'envoie le message not à true, ça va me rendre false. 26 00:01:35,920 --> 00:01:38,080 J'ai des objets, comment est-ce que j'implémente ça? 27 00:01:38,910 --> 00:01:42,310 Je vais d'abord vous donner une indication: la solution 28 00:01:42,510 --> 00:01:45,530 ne contient pas de conditions. En général, vous arrivez à 29 00:01:45,730 --> 00:01:47,630 avoir une solution qui a une condition, mais moi je vous 30 00:01:47,830 --> 00:01:49,840 assure que la solution que je propose ou que Pharo 31 00:01:50,040 --> 00:01:52,780 implémente en fait ne contient absolument aucune 32 00:01:53,000 --> 00:01:56,390 condition ou conditionnel. 33 00:01:56,590 --> 00:01:58,580 Vous n'avez pas de if dans la solution. 34 00:02:00,940 --> 00:02:04,720 Réfléchissez un peu pour voir si ça vous donne une idée. 35 00:02:05,030 --> 00:02:07,580 En général, ça ne marche pas trop ce genre d'indications. 36 00:02:07,820 --> 00:02:11,800 Donc je vais vous donner une deuxième indication: en 37 00:02:12,000 --> 00:02:13,130 fait la solution a trois classes. 38 00:02:15,050 --> 00:02:18,290 Elle a la classe Booléens qui est une classe abstraite. 39 00:02:18,490 --> 00:02:22,420 Elle a la classe True et la classe False. 40 00:02:24,000 --> 00:02:28,420 L'objet booléen true, c'est l'unique instance de la classe True. 41 00:02:28,620 --> 00:02:33,280 Vous voyez la différence, l' 42 00:02:33,480 --> 00:02:38,370 instance true commence par un petit t et la classe False 43 00:02:38,770 --> 00:02:40,320 commence avec une majuscule. 44 00:02:40,520 --> 00:02:44,450 False est l'unique instance de la classe False. 45 00:02:44,650 --> 00:02:46,060 Qu'est-ce que ça donne sur un schéma? 46 00:02:46,440 --> 00:02:48,860 On voit bien que true est instance de la classe True, 47 00:02:49,060 --> 00:02:50,450 false est instance de la classe False. 48 00:02:50,650 --> 00:02:52,620 Normalement avec cette indication-là, vous devriez me 49 00:02:52,820 --> 00:02:55,120 dire "C'est évident, la solution doit être comme ça. 50 00:02:55,320 --> 00:02:57,140 " Je ne sais pas si vous la voyez. 51 00:02:57,730 --> 00:02:58,780 On va la voir dans un moment. 52 00:02:59,000 --> 00:03:00,040 Je vous laisse un petit peu réfléchir. 53 00:03:00,740 --> 00:03:05,610 Je ne vais pas parler tout de suite de la 54 00:03:05,810 --> 00:03:08,760 solution, mais réfléchir de comment est-ce qu'on exprime 55 00:03:08,960 --> 00:03:11,230 finalement un choix dans un langage à objets. 56 00:03:12,710 --> 00:03:15,350 Un choix, on l'exprime en définissant des classes avec 57 00:03:15,550 --> 00:03:18,580 des interfaces qui sont compatibles, avec des méthodes 58 00:03:18,780 --> 00:03:21,200 compatibles et en envoyant un message à une instance. 59 00:03:21,400 --> 00:03:22,350 Donc là, c'est ce que j'ai illustré. 60 00:03:22,550 --> 00:03:23,310 Quand je fais x open, 61 00:03:27,430 --> 00:03:30,200 je vais choisir la bonne méthode associée à x. 62 00:03:30,400 --> 00:03:31,930 Ça veut dire que si c'est un fichier, ça va ouvrir un 63 00:03:32,130 --> 00:03:33,880 fichier; si c'est une fenêtre, ça va ouvrir une fenêtre 64 00:03:34,080 --> 00:03:36,060 ; si c'est un outil, ça va ouvrir un outil. 65 00:03:37,390 --> 00:03:40,720 La méthode va être sélectionnée suivant la base de la classe de x. 66 00:03:42,950 --> 00:03:45,950 Comment avec cette indication on peut maintenant avoir la 67 00:03:46,150 --> 00:03:49,620 solution? On va l'implémenter comme ça. 68 00:03:51,490 --> 00:03:52,250 Ça veut dire quoi ? 69 00:03:52,450 --> 00:03:55,210 Ça veut dire que j'implémente la méthode not dans la 70 00:03:55,410 --> 00:03:58,480 classe False et dans ces cas-là, je rends true. 71 00:03:58,790 --> 00:04:03,460 J'implémente la méthode not dans la classe True en rendant false. 72 00:04:04,750 --> 00:04:06,250 De manière visuelle, on obtient ça. 73 00:04:08,540 --> 00:04:11,640 Vous voyez que la solution n'a pas de conditions explicites. 74 00:04:12,110 --> 00:04:14,570 Je n'utilise pas un if à l'intérieur de ce genre de choses. 75 00:04:15,100 --> 00:04:17,260 Comment ça marche ? 76 00:04:17,460 --> 00:04:18,220 Ça marche comme ça. 77 00:04:18,420 --> 00:04:22,470 Ça veut dire que quand j'envoie le message not ici, où 78 00:04:22,670 --> 00:04:24,100 est-ce que je recherche la méthode not? 79 00:04:24,300 --> 00:04:27,470 Je la cherche dans la classe du receveur donc true est instance de True. 80 00:04:28,330 --> 00:04:30,830 Ah ben tiens, c'est cette méthode-là qui va être exécutée. 81 00:04:31,030 --> 00:04:31,790 Qu'est-ce que je dois faire ? 82 00:04:32,000 --> 00:04:32,750 Je dois rendre false. 83 00:04:32,950 --> 00:04:33,710 Ah ben tiens, ça marche. 84 00:04:33,910 --> 00:04:37,820 Maintenant, j'envoie un message à l'instance false. 85 00:04:38,020 --> 00:04:39,530 Je cherche où? Dans la classe de False. 86 00:04:40,370 --> 00:04:43,140 C'est ce not-là qui va être exécuté donc ça rend true. 87 00:04:43,340 --> 00:04:47,240 Donc, j'ai bien implémenté la négation de booléens avec 88 00:04:47,440 --> 00:04:49,160 deux méthodes sans avoir besoin de conditions. 89 00:04:55,260 --> 00:04:58,500 On peut regarder aussi l'implémentation de la super classe. 90 00:04:59,050 --> 00:05:00,860 La classe Booléens est une classe abstraite. 91 00:05:01,060 --> 00:05:04,640 Elle a deux sous-classes qui vont implémenter les opérateurs qu'il faut. 92 00:05:05,000 --> 00:05:08,140 Et en Pharo, on va exprimer que not est une méthode 93 00:05:08,340 --> 00:05:11,750 abstraite sur booléens en utilisant le message self subclassResponsability. 94 00:05:11,950 --> 00:05:16,680 Ça, c'est juste l'aspect Pharo de la chose, mais c'était 95 00:05:16,880 --> 00:05:17,640 pour être complet. 96 00:05:18,650 --> 00:05:20,880 Maintenant, normalement vous devriez avoir compris 97 00:05:21,230 --> 00:05:23,720 comment vous pouvez exprimer le comportement de |. 98 00:05:24,000 --> 00:05:25,460 Je vais vous laisser un petit moment pour exprimer ça. 99 00:05:25,660 --> 00:05:27,830 Là, l'idée c'est que vous allez devoir définir une 100 00:05:28,030 --> 00:05:32,070 méthode qui va prendre un argument de plus et qui suivant 101 00:05:32,270 --> 00:05:36,580 la valeur de cet argument, va rendre la bonne 102 00:05:36,800 --> 00:05:41,400 chose. Là, souvent vous allez dire "Il suffit que j'aie une condition. 103 00:05:41,600 --> 00:05:42,840 " Mais non, c'est ça le truc. 104 00:05:43,040 --> 00:05:46,210 Là, encore une fois, vous n'avez pas besoin de conditions 105 00:05:46,410 --> 00:05:51,230 pour implémenter |. Je vous laisse dix secondes pour réfléchir. 106 00:05:51,490 --> 00:05:53,070 Normalement, vous auriez dû préparer l'exercice. 107 00:05:53,270 --> 00:05:58,160 Là, je vais définir | sur la classe 108 00:05:58,360 --> 00:06:01,130 Booléens abstraite comme une méthode abstraite. 109 00:06:03,440 --> 00:06:08,210 Sur la classe False, je le vois c'est écrit, le 110 00:06:08,410 --> 00:06:10,330 receveur est de la classe False, qu'est-ce que je dois rendre? 111 00:06:11,310 --> 00:06:13,870 Ah ben tiens, quand c'est true, je rends true; quand c'est 112 00:06:14,070 --> 00:06:14,830 false, je rends false et quand c'est n'importe quoi, je 113 00:06:15,030 --> 00:06:17,740 rends n'importe quoi. Donc ça veut dire que je rends l'argument. 114 00:06:18,660 --> 00:06:23,500 Là, l'implémentation sur la classe False de |, c'est 115 00:06:23,700 --> 00:06:25,290 rendre l'argument qui est passé. 116 00:06:25,630 --> 00:06:26,500 Et c'est exactement ce qu'on fait. 117 00:06:29,290 --> 00:06:33,820 De la même manière, si on regarde sur la classe True, c'est 118 00:06:34,020 --> 00:06:37,400 expliqué là. 119 00:06:39,020 --> 00:06:43,780 Quand j'envoie | au receveur true, 120 00:06:44,030 --> 00:06:45,210 je rends le receveur. 121 00:06:45,630 --> 00:06:48,590 Donc là, je rends true. 122 00:06:48,790 --> 00:06:51,050 Vous voyez encore une fois que je n'ai pas de conditions, 123 00:06:51,680 --> 00:06:55,200 j'ai juste utilisé de l'envoi de message. 124 00:06:55,400 --> 00:06:59,130 De manière un petit peu plus propre, comment c'est écrit dans Pharo? 125 00:06:59,410 --> 00:07:04,360 On sait que true va être le receveur du message donc au 126 00:07:04,560 --> 00:07:06,490 lieu d'écrire true ici, on peut écrire self, c'est pareil. 127 00:07:07,100 --> 00:07:08,950 Si vous lisez la définition, vous pouvez voir self et 128 00:07:09,150 --> 00:07:10,930 vous pouvez vous dire "Ah ben oui, c'est normal puisque 129 00:07:11,130 --> 00:07:15,710 le receveur sera true donc ces deux écritures sont strictement équivalentes. 130 00:07:18,750 --> 00:07:19,510 " 131 00:07:19,710 --> 00:07:21,520 Là, encore une fois, si on regarde de manière visuelle, 132 00:07:21,810 --> 00:07:26,570 quand j'envoie le message | avec quelque 133 00:07:26,770 --> 00:07:30,430 chose ici à l'objet true, je vais chercher cette 134 00:07:30,630 --> 00:07:34,270 définition-là de | et elle va me rendre self. 135 00:07:34,470 --> 00:07:35,230 Donc, elle va me rendre true. 136 00:07:35,910 --> 00:07:39,630 Celle-là, quand j'envoie le message | avec quelque chose, 137 00:07:40,220 --> 00:07:42,590 je vais chercher dans la classe de False qui est False, 138 00:07:42,850 --> 00:07:46,790 donc je tombe sur cette implémentation-là, donc je vais rendre alpha. 139 00:07:47,790 --> 00:07:50,870 C'est bien les tables de booléens que je cherchais à 140 00:07:53,490 --> 00:07:54,250 implémenter. 141 00:07:55,000 --> 00:07:57,080 Ce qu'il faut voir, c'est que la solution qu'on a 142 00:07:57,280 --> 00:08:01,870 implémentée n'utilise absolument pas de conditions ou 143 00:08:02,070 --> 00:08:05,280 d’instructions conditionnelles comme une boucle explicite. 144 00:08:05,920 --> 00:08:06,680 Qu'est-ce qu'elle fait ? 145 00:08:06,880 --> 00:08:08,240 En fait, elle laisse le receveur décider. 146 00:08:08,900 --> 00:08:11,430 Ça veut dire que je dis à l'objet booléen qui reçoit le 147 00:08:11,630 --> 00:08:14,170 message "Trouve la bonne version, fais ce qu'il faut. 148 00:08:14,370 --> 00:08:17,840 " Je ne suis pas en train de prendre une décision par 149 00:08:18,040 --> 00:08:19,030 rapport à ce qui devrait être fait. 150 00:08:19,410 --> 00:08:21,050 C'est un principe qu'on va retrouver un petit peu 151 00:08:21,250 --> 00:08:23,680 ailleurs et qui est vraiment un principe fondamental objet. 152 00:08:23,880 --> 00:08:28,170 C'est les heuristiques dont on parlait au début du cours, 153 00:08:28,370 --> 00:08:29,470 c'est "Do not ask, tell. 154 00:08:29,670 --> 00:08:33,750 " Ça veut dire "Je ne veux pas exprimer une condition, je 155 00:08:33,950 --> 00:08:37,550 veux juste donner un ordre " Et ça, c'est une grande clé 156 00:08:37,750 --> 00:08:39,420 de la programmation-objet. 157 00:08:40,020 --> 00:08:42,630 Et l'autre, c'est "Laisse le receveur décider. 158 00:08:42,870 --> 00:08:46,100 " Je donne un ordre au receveur, c'est à lui d'encapsuler 159 00:08:46,300 --> 00:08:48,210 son savoir et de prendre les bonnes décisions.