Bonjour. Donc ce cours c'est un cours vraiment avancé.
Alors on va ouvrir le capot de Pharo et on va aller voir
comment les classes, et toutes les relations d'instances
entre classes sont gérées, donc c'est vraiment pour les curieux on va dire.
Donc ce qu'il faut bien voir, c'est que vous n'en avez
absolument pas besoin pour programmer en Pharo, la preuve
c'est que vous avez déjà programmé plein de petits
programmes et d'applications en Pharo, sans savoir comment ça marchait.
Maintenant moi je me dis qu'intellectuellement je serais
insatisfait si le cours ne me montrait pas comment ça
fonctionne à l'intérieur. Donc par exemple, moi je veux
savoir où est-ce que lui me définit, je veux savoir mais
c'est quoi la classe de Metaclass et, je veux comprendre tout ce bazar.
Donc c'est pour ça qu'on a fait ce cours, donc si vous ne
comprenez pas en première instance vous le mettez de
côté, ça ne vous empêchera pas de faire du Pharo, par
contre si vous avez vraiment envie de savoir ben vous l'écoutez
une deuxième fois ou une troisième fois si nécessaire.
Alors maintenant, il y a une clé qui est fondamentale et
qui est vraiment sympa, c'est ce transparent-là.
Avec ce transparent normalement vous devez comprendre.
L'idée de base c'est toujours la même chose; de toute
façon on ne fait que répéter ça dans ce MOOC, c'est quand
j'envoie un message à un objet qu'est-ce que je fais?
vous devez le savoir depuis le temps, je suis le lien d'instanciation,
je cherche dans la classe de l'objet et si je ne le
trouve pas, je remonte sur l'héritage.
Donc toujours ces 2 points.
Premièrement je vais sur la classe, deuxièmement je regarde dans l'héritage.
On va faire ça systématiquement, systématiquement et
systématiquement encore dans ce cours.
Donc les métaclasses pour les expliquer, on les explique
en 7 points et on va les dérouler un par un vous allez
voir, c'est relativement finalement c'est relativement simple.
Le premier point, chaque objet est instance d'une classe, ouh!
ça c'est dur.
Donc là j'ai l'objet "OrderedCollection", est instance de
la classe OrderedCollection. Voila jusque là ça va.
Donc le deuxième point, chaque classe va hériter
finalement de la classe objet.
Alors là ce qu'on voit c'est que OrderedCollection hérite
de SequenceableCollection qui hérite de Collection qui hérite de Object.
Pour info, Eventually, pour les petits Français, ça ne
veut pas dire éventuellement ça veut dire de manière sûre.
C'est un faux ami. Donc voilà, on a toujours notre grappe
d'héritage, qui va de toute façon venir pointer sur Object.
Donc qu'est-ce que c'est finalement que la responsabilité
de la classe Object ?
La classe object représente le comportement commun entre
tous les objets du système, donc la gestion des erreurs,
quand on est un break point, les annoncements et c'est la
racine de l'arbre d'héritage.
Vous pouvez aller voir ce qu'il y a dans objet.
C'est ça sa responsabilité première, c'est le comportement minimal.
Donc on revient à nos 7 points.
Chaque classe est instance d'une Metaclass.
C'est ce qu'on avait vu dans un cours précédemment, on a
dit une classe X, c'est l'unique instance de la Metaclass
qui s'appelle X classe.
Eh bien c'est ce qu'on voit OrderedCollection, la classe
OrderedCollection est instance de la classe OrderedCollection class.
La classe, SequenceableCollection, est instance de la
classe SequenceableCollection class.
Object, la classe Object, est instance de la classe Object class.
De toute façon toutes les classes du système sont
instances d'une autre Metaclass, qui a le même nom qu'elle,
suivie de class.
Donc les Metaclass en fait sont créées automatiquement
par le système quand vous créez une classe, elle sont
déjà créés, puis on envoie le message New à la Metaclass qui crée la classe.
Donc la question, la hiérarchie de Metaclass est
parallèle à la hiérarchie de class.
Ben oui, ça veut dire que tout à l'heure, on avait
spécifié que OrderedCollection est l'instance de
OrderededCollection class, que SequenceableCollection est
instance de Sequenceable class, maintenant on devait
spécifier quelle est la relation entre les 2.
Comme j'ai une relation d'héritage ici, eh ben j'aurai
une relation d'héritage ici.
Toujours. Donc c'est pour ça que on dit qu'on a cette
hiérarchie, ces 2 hiérarchies qui sont parallèles.
Donc qu'est-ce qui se passe, quand est-ce qu'on utilise cette hiérarchie?
Quand j'envoie le message "New", typiquement, à
OrderedCollection, je vais chercher où dans la classe, je
vais sur la classe donc OrderedCollection class, et je
cherche est-ce que tu as redéfini New?
Oui, non. Est-ce que tu as redéfini New?
Oui, non. Et caetera, et caetera.
D'accord.
Et donc là on voit bien que on reprend la clé que je vous
ai donnée en début de cours, qui est, je vais d'abord,
quand j'envoie un message je vais d'abord sur la classe
puis je suis l'héritage.
Maintenant jusque là, vous pouvez dire bon ben OK j'ai
compris, maintenant les questions qui nous intéressent c'est
Object class est instance de qui ?
C'est vrai ça quoi !
Et qui c'est la super classe de Object class.
Et qu'est-ce qui se passe ?
Est-ce que ça va marcher quand j'envoie un message à une Metaclass.
Et est-ce que ça va marcher quand j'envoie un message au
truc qu'il y aura ici ?
Ce sont les questions qu'on va voir maintenant.
Donc ce que le système dit, il dit chaque Metaclass
hérite de class ou jusqu'à Behavior on va dire.
Donc regardons ça.
Donc on répond à la première question "Object class c'est
une classe donc elle hérite de class, class hérite de
ClassDescription et Behavior.
Donc en fait dans Pharo, si on regarde par rapport à
certains autres systèmes comme les systèmes LISP, ils n'ont
qu'une seule classe pour Behavior ClassDescription.
Dans Pharo, c'est découpé parce qu'il y a de la
réutilisation, vous allez voir que Metaclass va se
brancher sous ClassDescription et, donc on va réutiliser
ClassDescription dans 2 cas de figure.
Et ce qu'on voit, c'est que Behavior, qui est l'essence
de ce que c'est qu'une classe, va pointer, va hériter d'objets.
Donc là par exemple, quand je vais envoyer un message
ici, il va se balader comme ça jusque là.
Parce que qu'est-ce qu'il fait ?
Ben il va au niveau classe puis il suit l'arbre d'héritage.
Donc la question de savoir où est- ce que New est défini?
New, la méthode qui crée des instances, elle est définie dans Behavior.
Donc quand j'envoie le message "New" à
"OrderedCollection", qu'est-ce qui se passe?
Je cherche dans la classe, première étape.
Est-ce que New est redéfini ?
Donc imaginons que New ne soit pas redéfini dans l'héritage,
je vais parcourir toutes les sous-classes, toutes les
super classes pardon, et je vais arriver sur New.
Et vous vous rappelez que le look-up c'est quoi?
C'est chercher une méthode et l'appliquer sur le receveur.
Et donc je vais trouver la méthode New que je vais appliquer sur qui?
Sur le receveur qui est la classe OrderedCollection et,
ça va me créer une nouvelle petite instance de
OrderedCollection, donc on va l'appeler je ne sais pas,
celle- là elle aura 3, 4 par exemple.
D'accord.
Et encore une fois, vous voyez la clé que je vous
expliquais au début du cours, c'est toujours la même
chose, quand j'envoie un message je cherche dans la
classe du receveur et je suis l'arbre d'héritage.
Donc si on regarde, là je ne veux pas aller trop loin
dans les détails, mais finalement qu'est-ce que c'est le Behavior?
Behavior c'est l'essence de ce que c'est qu'un objet qui
peut avoir des instances. Un objet qui peut avoir des
instances, en particulier, il doit avoir un lien de super
classe, un dictionnaire de méthode et une description des
instances, qu'on appelle souvent un format.
Et puis vous pouvez regarder dans la classe, j'ai pris
quelques-unes des méthodes, vous avez New, basicNew, newColonn.
Alors la différence entre new et basicNew, ce qui est
important c'est qu'il ne faut jamais faire de
redéfinition de basicNew, ça on l'a dit lors du cours sur
les méthodes, il ne faut jamais en Pharo redéfinir une
méthode qui commence par basic, parce que sinon vous ne
pourriez plus accéder à la méthode, à la méthode originale.
Donc il y a d'autres moyens, on peut accéder à toutes les
méthodes compilées, ce genre de choses.
Donc ça, je vous laisse regarder mais Behavior c'est l'essence
de ce que c'est qu'une classe.
ClassDescription qu'est-ce que c'est?
C'est une super classe abstraite qui va être partagée
entre class et metaclass et, qui ajoute des
fonctionnalités à Behavior comme la gestion du nom des
variables d'instances, parce qu'une classe a priori n'a
pas besoin d'être fait pour en humain pour être exécutée,
là classDescription va ajouter sur 2 choses: la
catégorisation des méthodes, les méthodes c'est ce que
vous avez dans le browser, quand vous avez le browser
avec les protocoles, on va dire cette méthode-là elle est
stockée dans le protocole printing par exemple.
La notion de noms aussi, la gestion des changements et le
fait que quand vous faites un changement, il est
enregistré dans un fichier et caetera.
Donc après, il faut regarder ce qu'il y a dedans, ce pas
très intéressant, mais cette décomposition elle est faite
parce que il y a réutilisation par ces 2 sous-classes.
Donc class, c'est la classe qui va représenter les
classes qu'on manipule dans Pharo.
Vous avez par exemple la gestion des variables partagées
qui sont des classes var, vous avez une meilleure façon
de nommer et de compiler des choses.
Donc vous encore une fois vous pouvez regarder dans le code.
Les classes sont des instances de metaclass, puisqu'on l'a
dit tout à l'heure. Quand j'ai dit que Object était
instance d'une classe, qui s'appelle Object class et que
OrderedCollection était une instance de OrderedCollection
class, ça marche aussi sur Class, ClassDescription et
Behavior, il n'y a pas de raison.
Donc Class est une instance de Class class, Description,
la classe Description est qui est un instance de la
ClassDescription class, et Behavior est une instance de
la classe Behavior class.
Et qu'est-ce qu'on a dit ?
On a dit qu'on avait l'héritage, que si j'ai une relation
d'héritage entre orderedCollection et Object, je dois
avoir la même relation d'héritage entre orderedCollection
class et Object class, donc je vais retrouver ce que j'ai
mis en gras sur les transparents, je vais retrouver cet héritage.
Et donc Behavior class hérite d'Object class.
Donc l'avant dernier point, chaque Metaclass est instance
d'une Metaclass, parce que la question qui se pose c'est
OK c'est très bien, de qui est instance
OrderedCollection class.
Parce que c'est un objet, puisque tout est objet dans Pharo.
Donc OrderedCollection class est instance de la classe Metaclass.
Object class est instance de Metaclass.
Class class est instance de Metaclass, classDescription
class est l'instance de Metaclass.
Donc toutes les Metaclass du système sont instance de Metaclass.
Et maintenant Metaclass elle qu'est-ce qu'elle fait?
Elle hérite de ClassDescription, parce qu'elle va dire ah
ben moi je suis une classe un peu particulière, je n'ai
qu'une seule instance en fait.
Et vous ne pouvez pas donner mon nom parce que mon nom il
est défini par le nom de mon instance, ce qui est un peu
barbare mais c'est comme ça.
Donc là ce qu'on voit, c'est que OrderedCollection est
instance d'OrderedCollection class et, que
orderedCollection class a comme nom dans celui de son instance.
Donc chaque Metaclass est instance de Metaclass.
Donc en fait si on regarde dans le code, Metaclass, sa
principale responsabilité et existence, c'est de créer, d'
initialiser une unité instance d'elle-même.
Donc il nous reste une seule question maintenant, à
laquelle on doit répondre mais, c'est de qui est instance
la Metaclass? La Metaclass elle est instance, parce que
c'est une classe comme OrderedCollection, c'est la même
chose, elle est instance de la classe Metaclass class.
Et si on regarde Metaclass hérite de ClassDescription,
donc Metaclass class hérite de ClassDescription class.
De la même manière que j'avais OrderedCollection class
hérite de Object class car OrderedCollection hérite de Object.
Donc ce qu'on voit, c'est que Metaclass est instance de
Metaclass class, de la même manière que OrderedCollection
était instance d'OrderedCollection class.
Et maintenant, Metaclass class, elle, est instance de
Metaclass, de la même manière que Class class, Object
class et OrderedCollection class sont instance de Metaclass.
Ça fait un peu bizarre de voir ce petit noyau, mais c'est
normal, c'est cohérent avec l'ensemble de la chose.
Effectivement, vous n'en avait pas besoin pour programmer
en Pharo, donc vous pouvez l'oublier.
Maintenant ce qui est intéressant dans ce graphe, c'est
que la clé que je vous ai donnée en début de cours, elle
fonctionne parfaitement dedans.
Ça veut dire qu'à chaque fois que vous envoyez un message
à un objet, on va regarder sa classe et, parcourir l'arbre d'héritage.
Et là j'aimerais faire quelques quelques exemples avec
vous commençons par le début.
J'envoie un message à cet instance-là, qu'est-ce qui va se passer?
Je viens sur Object.
Si j'envoie un message à la classe, je vais aller sur la
Metaclass et je vais remonter l'arbre d'héritage.
Comme ça.
Si j'envoie un message à une Metaclass où est-ce que je dois chercher?
Dans mes 2 class puisque ma Metaclass orderedCollection
class est instance de Metaclass.
Donc je vais chercher comme ça, je vais suivre le lien d'instanciation,
je vais remonter ici et, là par exemple si j'ai un
message qui n'est pas compris ou si j'ai une méthode qui
est que définie sur Object, c'est le chemin qui le fait.
Maintenant si j'envoie un message sur Metaclass elle-même.
J'envoie un message sur Metaclass, où est-ce que je vais chercher?
Je vais chercher sur Metaclass class d'abord, puis je
remonte l'arbre d'héritage. Donc là
ici, voilà, je ne vous voyez plus et celui-là c'est le plus compliqué.
De la même manière si j'envoie un message sur Metaclass,
celui-là il est plus simple, si j'envoie un message sur
Metaclass class, c'est la même chose qu'envoyer un
message sur OrderedCollection class, où est-ce que je vais chercher?
Je vais chercher dans l'instance de Metaclass class, qui
est Metaclass, et donc je vais chercher, je vais faire
exactement le même parcours que pour OrderedCollection
class, je vais suivre ce chemin-là.
Ce que je voulais vous montrer avec ce graphe, c'est qu'il
est complètement cohérent en fait.
Vous ne pouvez pas avoir un graphe incohérent, pourquoi?
Parce que la machine virtuelle ne fait qu'une seule chose.
Quand vous envoyez un message à un objet, il cherche dans
la classe de l'objet et remonte l'arbre d'héritage.
Et ce graphe, qui en fait parait complet, est
complètement uniforme par rapport à ça et cohérent.
Donc ça, c'est ça que je trouvais un petit peu excitant
parce que moi je me suis posé des questions et je
trouvais ça vraiment sympa.
Donc qu'est-ce que vous devez savoir?
Que les classes sont des objets, qu'elles peuvent
recevoir des messages, que le processus est exactement le
même que pour n'importe quel objet.
Alors après bien sûr avec un petit peu la complexité qu'on
a des Metaclass qui ont une instance unique et, qui ne
sont pas nommées explicitement.
Mais ça vous n'en avez pas besoin pour programmer en Pharo.