8. Classes
Programmation orientée objet
La programmation orientée objet (POO) est une approche très répandue de la programmation et supportée aujourd'hui par la plupart des langages informatiques. Elle consiste à définir des entités, représentant des concepts abstraits ou concrets, possédant des propriétés et des comportements spécifiques. L'utilisation des objets est incontournable, par exemple, dans la conception d'IHM (Interfaces Homme-Machine) graphiques pour nos applications. Les boutons, les fenêtres, les données que l'on traite etc. sont des exemples d'objets.
Une grande partie des langages supportant les objets requiert de définir des classes qui sont en quelque sorte des types ou des modèles d'objets. Par exemple, on aura une classe "Bouton" qui définira les propriétés et les comportements attendues de tous les boutons (une forme graphique, un libellé, un état, une aptitude à déclencher des actions etc.). A partir de cette classe, des objets "boutons" particuliers pourront être définis, possédant un comportement particulier, par exemple le bouton "Exit" qui permet de quitter une application. Les classes peuvent donc être comprises comme des ensembles dont les éléments, appelés aussi instances, sont des objets.
Avec la programmatrice, il est possible de définir des classes. Ces classes se présentent comme des modules particuliers destinés à servir de modèles pour définir d'autres modules, qui seront alors des modules objets, ou instances de classe.
Pour mieux saisir cela, voyons comment concrètement on utilise ces possibilités avec la programmatrice et prenons un exemple.
Tout d'abord, c'est toujours l'instruction define qui permet de créer une classe, comme ceci :
-
define C1 : Class
Comme pour les modules, cette commande crée un module classe C1 et sélectionne ce nouveau module comme module courant. On pourra alors définir les éléments (propriétés ou membres) de la classe comme on le fait dans un module.
Par exemple, on pourra définir une classe Rectangle en déclarant ses propriétés (variables membres) longueur et largeur ainsi que les méthodes de calcul du périmètre et de la surface (fonctions membres). Cette classe servira ensuite à créer des instances de Rectangle, r1 et r2, qui auront leurs dimensions particulières.
Par exemple :
---? define Rectangle:Class
---= ok
On déclare les propriétés
---? add long:int, larg:int
---= ok
On déclare les méthodes
---? define perimetre
---= ok
En-tête :
perimetre :int
Corps :
2 * (long+larg)
---? define surface
---= ok
En-tête :
surface :int
Corps :
long * larg
---? define info
---= ok
Une méthode permettant d’afficher toutes infos
En-tête :
info
Corps :
write "Longueur=" ++ long ++ ", Largeur=" ++ larg;
write "Perimetre=" ++ perimetre;
write "Surface=" ++ surface
Constructeur
---? define _init
---= ok
En-tête :
_init (a:int, b:int)
Corps :
long, larg = (if a<b then b,a else a,b fi)
La méthode _init est appelée « constructeur ». Son nom _init est prédéfini. Elle est utilisée pour initialiser les instances de la classe.
On peut afficher la liste des éléments de la classe.
---? ls
*long : int
*larg : int
_init : Function
info : Function
perimetre : Function
surface : Function
---= ok
N.B. L’ordre des éléments peut être différent, il ne dépend pas de l’ordre des définitions.
Dans les classes, les variables sont par défaut abstraites i.e. elles ne peuvent pas prendre de valeur. C’est pourquoi, dans la liste, une '*' précède leur nom.
Les propriétés ainsi définies sont destinées aux instances de la classe, pas à la classe elle-même. Si on les utilise depuis la classe, on aura des messages d’erreurs.
Exemple :
---? long = 54
*** Abstract 'long' cannot be assigned
---? info
Longueur=(), Largeur=()
*** Undefined value
*** Undefined value
Création d’instances
Une fois la classe définie, celle-ci peut servir comme type de variable et des instances peuvent être crées grâce à la fonction prédéfinie new.
Exemple :
On remonte au module père de la classe Rectangle
---? cd ..
---= ok
---? add r1:Rectangle
---= ok
---? add r2 = new Rectangle 10,12
---= ok
---? r1 = new Rectangle 50,12
---= ok
---? r1.info
Longueur=50, Largeur=12
Perimetre=124
Surface=600
---? r2.info
Longueur=12, Largeur=10
Perimetre=44
Surface=120
Le constructeur _init est utilisé implicitement lors de la création par new de chaque instance. Dans l’exemple, pour la création de r2, implicitement on a effectué l’appel _init(10,12).