La programmation par objets Principes et concepts Etude de Smalltalk
Smalltalk-80 – Vue générale Smalltalk-80 Langage Environnement de programmation Historique Concepts Génie logiciel Réflexivité Parallélisme MVC Java a été influencé par C / C++ pour la syntaxe Smalltalk pour plusieurs concepts et la librairie
Historique Simula 67 objets classes héritage FLEX envois de messages Lisp interprète environnement interactif Logo Syntaxe Tortue (environnement graphique) Langage de programmation Système d’exploitationEnvironnement de programmation interactif Environnement graphique ST-72 ST-76 ST-80 LIBERTÉ !!!
Axiomes 1. Tout entité du langage est un objet (uniformité) 2. Tout objet est instance d’une classe (uniformité) 3. L’héritage est simple 4. La seule structure de contrôle est l’envoi de messages (uniformité) Tout est accessible / modifiable par l’usager
Concepts primitifs Objet Message Classe (héritage) Instance Méthode
OBJET Objet = nommées indexées Support de la modularité Le fonctionnement de tout objet est indépendant des détails internes des autres objets Activation du comportement Transmission de messages Séparation Intention de l’émetteur Méthode employée par le récepteur pour la réalisation de cette intention MODULARITÉ Le seul moyen Uniformité Renforcer l’utilisation d’abstractions pour assurer avantages
Exemple sémantique 1 Sélecteur : + Argument : 2 Sélecteur : + Argument : 2 MESSAGES Message == OBJET (respect de A1) sélecteurarguments Structures de contrôle traditionnelle messages Exemple2 : conditionnelle x = y ifTrue: [ egalite <- ‘egal’ ] ifFalse: [ egalite <- ‘distinct’] sélecteur arguments Bloc : évaluation différée Objets + Envois de messages Tout ce qu’il faut pour construire l’environnement de programmation
CLASSES Une vision platonique des objects Abstraction L’essence précède l’existence Classification d’objets similaires Factorisation de descriptions des objets individuels
Prototypes L’existence précède l’essence Clones Délégation Exemple : Javascript
Factorisation des descriptions Structure Comportements Variables d’instance (état) nommées indexées (Array) Dictionnaire des méthodes Sélecteur Paramètres Variables temporaires Séquence d’expressions objet
Classe = objet + capacité de générer des objets instances x = 1 y = 2 initinit x y y: x = 3 y = 4 initinit x y y: FACTORISATION Classe Point Structure : { x, y } Comportements : { x, y, y:, init }
INSTANCIATION Interprétation des messages Lien d’instanciation Ma classe connaît mon comportement
i-v = { x, y } Point initialize x := 0. y := 0. y: unEntier y := unEntier. y ^y i-v = { direction } Tortue initialize super initialize. direction := 270 avance: n self av: n av: n n>0 ifTrue: [self y: self y + 1. self av: n – 1.] Hérite de x=0 y=0 direction = 270 avance: 10 Instance de
INSTANCIATION Création d’une instance Transmission de message Point new (uniformité) Interprétation des messages Lien d’instanciation Ma classe connaît mon comportement
Réflexivité structurelle Tout est objet (A1) Une classe est un objetTout objet est instance d’une classe (A2) Une classe est instance d’une classe sa métaclasse anonymecréée automatiquement Méthodes de classes (comportement de la classe) Ex: new, subclass: mais, ClassTalk Architecture réflexive tout est disponible on peut modifier le fonctionnement de l’instanciation 1er type de hiérarchie : graphe d’instanciation
classVariables = Dessin Point class newInit ^self new initialize pool : ICONES { (Smiley, ), (Slomo, ;-) } Tortue class initialize [[true] whileTrue: [ Time avantMidi ifTrue:[ Dessin := Slomo] ifFalse: [ Dessin := Smiley] ]] fork Hérite de i-v = { x, y } Point initialize x := 0. y := 0. y: unEntier y := unEntier. y ^y i-v = { direction } Tortue initialize super initialize. direction := 270 avance: n self av: (Dessin = Slomo ifTrue: [n/2] ifFalse: [n]) av: n n>0 ifTrue: [self y: self y + 1. self av: n – 1.] Hérite de Instance de newInit x=0 y=0 direction = 270 Instance de avance: 10
classVariables = Dessin Point class newInit ^self new initialize i-v = { x, y } Point initialize x := 0. y := 0. y: unEntier y := unEntier. y ^y Instance de
Héritage Réutilisation Partage Factorisation Classification des descriptions de variables d’instance méthodes 2e type de hiérarchie : graphe d’héritage
Héritage : exemple d’utilisation i-v = { x, y } Méthodes = { x:, y: } Point i-v = { x, y, direction } Méthodes = { x:, y:, avance } Tortue Tortue == Point + epsilon
classVariables = Dessin Point class newInit ^self new initialize pool : ICONES { (Smiley, ), (Slomo, ;-) } Tortue class initialize [[true] whileTrue: [ Time avantMidi ifTrue:[ Dessin := Slomo] ifFalse: [ Dessin := Smiley] ]] fork Hérite de i-v = { x, y } Point initialize x := 0. y := 0. y: unEntier y := unEntier. y ^y i-v = { direction } Tortue initialize super initialize. direction := 270 avance: n self av: (Dessin = Slomo ifTrue: [n/2] ifFalse: [n]) av: n n>0 ifTrue: [self y: self y + 1. self av: n – 1.] Hérite de Instance de newInit x=0 y=0 direction = 270 Instance de avance: 10 Héritage des méthodes y: et y sans réutilisation
Héritage spécialisation La superclasse doit d’abord être définie Possible de modifier l’arbre d’héritage Variables d’instance aucune redéfinition ajout (extension) méthodes ajoutmasquage avecsans réutilisation directe extension de l’environnement Héritage est dynamique Recherche à chaque réception de messages Héritage est statique calculé une seule fois à la création
Auto-référence Self Objet qui a reçu le message Pour qu’un objet puisse invoquer ses propres méthodes Appliquer la méthode la plus spécialisée Méthodes récursives Pour qu’un objet puisse se passer en paramètre Super Objet qui a reçu le message + modification de l’algorithme de recherche La recherche commence dans la superclasse de la classe où est utilisé “super” Raffiner la factorisation Spécialisation avec réutilisation de méthodes héritées
classVariables = Dessin Point class newInit ^self new initialize pool : ICONES { (Smiley, ), (Slomo, ;-) } Tortue class initialize [[true] whileTrue: [ Time avantMidi ifTrue:[ Dessin := Slomo] ifFalse: [ Dessin := Smiley] ]] fork Hérite de i-v = { x, y } Point initialize x := 0. y := 0. y: unEntier y := unEntier. y ^y i-v = { direction } Tortue initialize super initialize. direction := 270 avance: n self av: (Dessin = Slomo ifTrue: [n/2] ifFalse: [n]) av: n n>0 ifTrue: [self y: self y + 1. self av: n – 1.] Hérite de Instance de newInit x=0 y=0 direction = 270 Instance de avance: 10 Héritage de la méthode initialize avec réutilisation
Les variables Variables temporaires Allouées le temps d’exécution de la méthode Variables d’instance nommées ou indexées variables privées d’un objet ne sont référençables que par les méthodes de l’objet Variables de classe Partagées par Instances de la classe Instances des sous-classes Variables “pool” Globales Partagées par les instances d’un ensemble de classes Dictionnaire (clé-valeur) Clé = symbole = nom de la variable Les clés sont directement référencées dans les méthodes Variables globales Accessibles de n’importe où dans le système Ex.: noms des classes
classVariables = Dessin Point class newInit ^self new initialize pool : ICONES { (Smiley, ), (Slomo, ;-) } Tortue class initialize [[true] whileTrue: [ Time avantMidi ifTrue:[ Dessin := Slomo] ifFalse: [ Dessin := Smiley] ]] fork Hérite de i-v = { x, y } Point initialize x := 0. y := 0. y: unEntier y := unEntier. y ^y i-v = { direction } Tortue initialize super initialize. direction := 270 avance: n self av: (Dessin = Slomo ifTrue: [n/2] ifFalse: [n]) av: n n>0 ifTrue: [self y: self y + 1. self av: n – 1.] Hérite de Instance de newInit x=0 y=0 direction = 270 Instance de avance: 10 Les variables temporaires, d’instance, de classe, Pool, globales
Model-View-Controller Fondé sur les dépendances Coordonner les activités de plusieurs objets Self changed Self myDependents update Construction d’une interface multi-fenêtres en Smalltalk Modèle (source d’information) texte Vue (représentation visuelle du modèle) Affichage du texte Contrôleur (interaction de l’usager avec le modèle) clavier
Réflexivité structurelle complètemétaclasses opératoire partielledoesNotUndertstand: aMessage thisContext become: anObject perform: aMessage Héritage multiple Redéfinition du traitement des messages
Conception Typage Pas de vérification à la compilation Les erreurs sont détectées à l’exécution Extension : TypedSmalltalk Encapsulation, interface Modifications locales Pas d’accès externes à l’état d’un objet Seules les méthodes y ont accès Il faut donc définir des méthodes d’accès appropriées Pas de méthodes cachées Polymorphisme et classes abstraites Fondé sur les sélecteurs Classes abstraites Possible de déléguer aux sous-classes l’implémentation d’opérations spécialisées
classVariables = Dessin Point class newInit ^self new initialize pool : ICONES { (Smiley, ), (Slomo, ;-) } Tortue class initialize [[true] whileTrue: [ Time avantMidi ifTrue:[ Dessin := Slomo] ifFalse: [ Dessin := Smiley] ]] fork Hérite de i-v = { x, y } Point initialize x := 0. y := 0. y: unEntier y := unEntier. y ^y i-v = { direction } Tortue initialize super initialize. direction := 270 avance: n self av: (Dessin = Slomo ifTrue: [n/2] ifFalse: [n]) av: n n>0 ifTrue: [self y: self y + 1. self av: n – 1.] Hérite de Instance de newInit x=0 y=0 direction = 270 Instance de avance: 10