Lisaac/Slot
Question : Et ensuite comment j'écris des attributs ?
modifierPour illustrer mon propos nous allons écrire un petit prototype modélisant les vecteurs à deux dimensions. Pour pouvoir représenter des points du plan par exemple.
Section Header + name := VECTOR_2; - category := MICRO; Section Inherit - parent_object:OBJECT := OBJECT; Section Public + x : NUMERIC := 0; + y : NUMERIC := 0;
Q : Mais si je mets les slots x et y qui représentent des attributs dans la section publique je ne respecte pas le principe de protection des données !?
modifierSi pas de problème car toute affectation de slot est interdite pour les autres prototypes. Public veut seulement dire que les autres prototypes ont un accès en lecture et pas en écriture. Pour faire un accès en écriture il suffit de faire un setter comme d'habitude. En fait c'est très important car c'est la seule façon de respecter complètement et facilement le principe d'encapsulation de l'implémentation et de protection des données. Ce qui veut dire que vous n'aurez pas besoin d'écrire un getter qui ne sert qu'à pallier la syntaxe et le modèle de protection des données de certains langages.
Exemple de setter :
Section Header + name := VECTOR_2; - category := MICRO; Section Inherit - parent_object:OBJECT := OBJECT; Section Public + x : NUMERIC := 0; + y : NUMERIC := 0; + set_x new_x:NUMERIC <- ( x:= new_x; ); + set_y new_y:NUMERIC <- ( y:= new_y; );
Q : Que représente NUMERIC ?
modifierNUMERIC est le prototype de la bibliothèque standard représentant tous les nombres, comme les différents entiers et flottants. Plus exactement, NUMERIC possède comme fils:
- SIGNED les nombres signés
- SMALLINT entier de 8 bits signé
- SHORTINT entier de 16 bits signé
- INTEGER entier de 32 bits signé
- LONGINT entier de 64 bits signé
- REAL_16_16 flottant de 16 bits de mantisse et 16 d'offset
- REAL_24_8 flottant
- DOUBLE flottant
- UNSIGNED les nombres non signés
- USMALLINT entier de 8 bits non signé
- USHORTINT entier de 16 bits non signé
- UINTEGER entier de 32 bits non signé
- ULONGINT entier de 64 bits non signé
- ULARGEINT entier non signé de longueur quelconque
Q : Comment cela se fait que l'on puisse affecter directement des valeurs aux slot x et y ? Cela devrait se faire dans le constructeur selon le principe de création et d'initialisation des objets !
modifierÉtant donné que les prototypes sont directement "vivants" en mémoire et qu'il n'y a pas vraiment de constructeur au sens classique il est logique de penser qu'il faut un moyen d'initialiser les slots pour le premier prototype présent en mémoire. (Il y aura plus d'explication dans une des parties suivantes)
Q : Et pour les méthodes ?
modifierEn fait c'est pareil que les slots de données : nous allons affecter un bloc d'instructions aux slots !
Il y a deux manières d'affecter des objets à un slot :
- avec l'opérateur d'affectation classique ":=" qui provoque une évaluation immédiate
- avec l'opérateur d'affectation "<-" qui provoque une évaluation retardée (ou paresseuse).
Pour déclarer un bloc il faut écrire une suite d'instructions séparées par des points virgules et encadrée par des parenthèses. En fait c'est très classique sauf que l'on utilise des parenthèses et que les blocs peuvent apparaître du côté droit d'une affectation. Pour affecter votre bloc dans le slot nous avons donc deux choix :
- avec := ce qui provoque l'exécution immédiate (sans appel). Peut être utile dans certain cas
- avec <- qui attend que l'on appelle le slot pour l'exécuter. C'est cela que l'on va utiliser dans la plupart des cas.
(par contre pour les slots de données on utilise plutôt :=)
Enfin pour renvoyer une valeur il suffit de placer cette valeur en dernière instruction et de ne pas la terminer par un point-virgule. Si la dernière expression d'un bloc est terminé par un ";" cela correspond à une procédure. Le type de la valeur de retour doit bien sur correspondre au type du slot. En fait les expressions en Lisaac sont déclarées de la même manière que les suites d'instructions : "(2+4<=2)" c'est pour cela que les valeurs de retours ont cette forme.
Section Header + name := VECTOR_2; - category := MICRO; Section Inherit - parent_object:OBJECT := OBJECT; Section Public + x : NUMERIC := 0; + y : NUMERIC := 0; + norme_au_carre : NUMERIC <- ( x*x+y*y );
Q : Je trouve cette façon d'écrire une méthode étrange, non ?
modifierEn fait en Lisaac il n'y a pas beaucoup de différences entre une méthode et un attribut. Que ce soit pour la définition ou pour l'utilisation. Ici les attributs et les méthodes possèdent la même interface c'est pour cela qu'on les désigne tous les deux sous le vocable de "slot". En particulier, un slot de code peut devenir un slot de données. Voir par exemple Transformer une méthode en attribut (ou l'inverse) dans le deuxième chapitre. Cette particularité n'est pas là seulement pour faire beau, comme nous le verrons dans tout le document c'est un des concept centraux de Lisaac.
Résumons : dans l'esprit de Lisaac vous affectez une liste d'instructions entre parenthèses à un slot. Nous avons utilisé ici la section Public qui permet à n'importe quel prototype d'appeler les slots.
Q : Je ne pensais pas a avoir à demander cela mais pour l'appel il y a aussi des particularités ?
modifierPour appeler un slot, ou envoyer un message suivant la façon de voir les choses, il suffit classiquement d'intercaler un point entre le prototype et le slot. Exemple :
x:=4; x.sqrt.print;
La particularité étant que l'on peut appeler un slot sans argument sans ajouter des parenthèse "()" inutiles : Ce qui permet notamment de remplacer un slot de donnée par un slot de routine, ou le contraire, sans changer l'interface du prototype. Ainsi le principe d'encapsulation objet est respecté au maximum.
TODO : dans quel cas peut-on supprimer les parenthèses si il y a des paramètres
Q : Pourquoi ne pas utiliser un "return x" comme d'habitude
modifierIl y a quelques problèmes avec l'instruction return provenant du langage C. Elle provoque en effet une rupture dans le flot d'exécution du programme. De plus les principes de la programmation structurés disent que la structure du code doit refléter les flots d'exécution possible. Ainsi la fin d'une routine ne doit arriver que lorsque que l'on arrive à la fin du bloc. Et c'est le même problème avec des instructions comme exit ou break.
Q : Si tout est objet il faudra que je me tape des 2.add(2) ?
modifierNon, rassurez-vous les opérateurs sont redéfinissables. On définit les symboles entre quotes ' '
Exemple l'addition pour notre prototype :
- '+' left 80 other:VECTOR_2 :VECTOR_2 <- (etc ...)
Et en plus vous avez le droit de choisir l'associativité gauche ou droite ainsi que la priorité.
Q : Que signifie les '+' et '-' devant les slots de données ?
modifier- Le '+' sert à faire un slot de données non partagé par les instances, c'est le cas le plus classique. Chaque instance a son propre slot.
- Le '-' sert par contre a partager le slot de données, cela équivaut aux variables static en C.
Q : Que signifie les '+' et '-' devant les slots de code ?
modifier- Le '+' sert comme d'habitude à ne pas partager le slot. C'est relativement rare pour un slot de code.
- Le '-' provoque le partage par toutes les instances de la méthode. C'est le cas le plus courant.