Classes et objets
Sisal permet de déclarer des classes et des objets. Une classe est une structure comprenant des données et des méthodes, un objet est une variable Sisal dont les caractéristiques sont définies par une classe; on dit que tel objet est de telle classe, ou un objet est une instance d'une classe.
Les classes sont définies par la déclaration TYPE, les objets sont définis comme les autres variables par la déclaration VAR. Une classe peut hériter de la définition d'une autre classe [1] , on dit alors de cette classe qu'il s'agit de la classe parent.
Type
NomDeClasse Class [ClasseParent] begin
{ Constante; | Membre; | Methode;}
end
La déclaration d'une constante
NomDeConstante Const ValeurConstante;
La déclaration d'un membre
NomDeMembre [Static] [ Classe | Structe | List | ...];
La déclaration d'une méthode
[Function] NomDeMethode ( [ Parametre [ = ValeurConstante] {, Parametre [= ValeurConstante]}]);
[Function] Create( [ Parametre [ = ValeurConstante] {, Parametre [= ValeurConstante]}]);
[Function] Delete();
La déclaration d'un opérateur [2]
operator{ + | - | * | / | []}( [ Parametre [ = ValeurConstante] {, Parametre [= ValeurConstante]}]);
Une méthode peut définir des paramètres par défaut, lors de l'appel d'une méthode les paramètres non renseignés sont remplacés par la valeur par défaut correspondante.
La méthode Create (mot réservé) est exécutée à la création de l'objet ;
La méthode Delete (mot réservé) est obligatoirement sans paramètres et est exécutée juste avant la destruction d'un objet. La destruction d'un objet a lieu lorsque la dernière référence à cet objet est supprimée ; par exemple pour un objet global ce sera avant l'arrêt du serveur ou du synoptique, pour un objet local à une fonction ce sera à la sortie de la fonction à la condition que cet objet n'ait pas été référencé dans une structure globale conservant une référence sur cet objet ( par exemple si on fait MaListeGlobal.Add( MonObjetLocal)).
Plus loin dans le code on pourra avoir la définition de la méthode.
Function NomDeClasse.NomDeMethode( [ Parametre {, Parametre }])
[ Var { variable;}]
[ Begin { instructions; } end]
;
Par exemple définissons les classes Point et Figure:Type
Point Class begin Pi const 3.141592; X; Y; Est() begin return « Point »; end; Distance() begin return sqrt( x*x + y*y); end;
Figure Class Point begin Forme; Create( forma) begin Forme = forma end; Est() begin return « Figure »; end; end;
La déclaration « Figure class point begin... » indique qu'une figure est un point donc elle dispose en standard des champs X et Y et des deux méthodes Est et Distance. On remarque aussi que la méthode Est est redéfinie, c'est ce que l'on appelle une méthode virtuelle.
On va pouvoir déclarer des objets.
Var MonPoint Point; MaFigure Figure;
... Begin MaFigure.X = 4; MaFigure.Y = 3; MaFigure.Forme = "Carré"; Message( MaFigure.Est():" est à ":MaFigure.Distance()); End
Cet exemple va afficher « Figure est à 5 », essayons de comprendre pourquoi.
La notation pointée permet d'accéder aux membres et méthodes d'un objet.
Une méthode est une fonction toujours intrinsèquement lié à un objet, cet objet est en fait le premier paramètre d'appel de la fonction, on peut le référencer sous l'identifiant « this » [3] .
Dans le corps de la méthode les membres et méthodes de l'objet sont accédés directement sans les préfixer par la notation pointé.
Donc « MaFigure.X » valorise le champ X de l'objet MaFigure.
« MaFigure.Distance() » effectue l'appel de la méthode Distance de Point car Figure.Distance n'est pas déclarée et donc on recherche successivement les parents jusqu'à tomber sur une déclaration.
MaFigure.Est() effectue l'appel de Figure.Est car MaFigure est une instance de Figure, et la méthode Est a été redéclarée dans Figure. Ce n'est pas simplement l'écrasement de la déclaration de Point.Est par Figure.Est, car ce sont des méthodes virtuelles c'est à dire que si dans un traitement quelconque on vient à traiter une figure comme une simple fonction, dans un paramètre de fonction par exemple, alors la méthode appelée est celle qui correspond au type effectif de la variable.
Par exemple
Function EnVrai( UnPoint Figure) begin return UnPoint.Est(); end ... Var MaFigure Figure; ... Message( EnVrai( MaFigure));
Dans ce cas EnVrai retourne « Figure », car bien que on ait déclaré en paramètre un point, ce qui a été transmis en paramètre lors de l'appel est en fait une figure.
Enfin si dans une méthode on souhaite appeler une méthode virtuelle d'une classe ascendante on préfixe le nom de la méthode du nom de la classe ascendante (par exemple Point.Est();).
Pere class begin nom ; create( n_om) ; end
Fils class pere begin age; create( n_om, a_ge); end
Fils.create( n_om, a_ge) begin pere.create( n_om); // Ici on appele le create du pere age = a_ge; end
[1] Pour le moment (version 4.0) il n'y a pas d'héritage multiple, c'est à dire qu'une classe ne peut pas être la fille de plusieurs classes.
[2] Un opérateur est pour la classe une methode particuliere qui permet de simplifier des expressions comme la l'addition de deux matrices (cf.$opérateur).
[3] This n'est défini que dans le corps d'une méthode de classe.