Vous êtes sur la page 1sur 13

Objets, blocs et portée

Thierry Lacoste

27 octobre 2007
Nous abordons deux questions :
1. Comment est introduit un nom pour un objet ?
2. Dans quelle partie du programme existe-t-il ?

1
Chapitre 1

Déclarations d’objets et
affectation

Définition : En Ada, un objet désigne une variable ou une constante.

1.1 Déclarations de variables


Une variable est introduite dans un programme par une déclaration ;
une valeur initiale peut lui être donnée.
Exemple : Nous pouvons écrire :

I : Integer;
P : Integer := 13;

Ces deux déclarations introduisent respectivement


1. une variable I de type Integer, sans lui donner de valeur initiale ;
2. une variable P de type Integer, qui reçoit 13 comme valeur initiale.
Attention ! On ne doit rien supposer sur le contenu d’une variable non
initialisée. Il ne faut donc pas utiliser la valeur d’une telle variable.

1.1.1 Déclarations multiples


Il est possible d’introduire plusieurs variables en même temps en une seule
déclaration :

2
I, J, K : Integer;
P, Q, R : Integer := 13;

Remarque. Le compilateur interprète une déclaration multiple comme la


suite des déclarations équivalentes. Ce que nous venons d’écrire est donc
traduit en :

I : Integer;
J : Integer;
K : Integer;
P : Integer := 13;
Q : Integer := 13;
R : Integer := 13;


Cette remarque est importante surtout lorsqu’une initialisation fait inter-
venir un appel de fonction.
Exemple :

A, B, C : Integer := Sqrt (2000);

Cette triple déclaration sera traduite par le compilateur en :

A : Integer := Sqrt (2000);


B : Integer := Sqrt (2000);
C : Integer := Sqrt (2000);

Nous aurons donc trois appels à la fonction Sqrt. Si l’appel est coûteux, on
préfèrera écrire :

A : Integer := Sqrt (2000);


B, C : Integer := A;


Notre remarque est importante surtout lorsque la fonction appelée lors
de l’initialisation comporte des effets de bord, c’est à dire si elle modifie
l’état de variables globales ou des périphériques.
Exemples :

3
1. Si la fonction Sqrt1 imprime un message, voire l’exécution bord1.log2
du programme bord1.adb3 comparée à l’exécution bord1bis.log4 du
programme bord1bis.adb5 .
2. Si on veut compter le nombre d’appels à une fonction, il faut procéder
par effet de bord. Voire l’exécution bord2.log6 du programme bord2.adb7
comparée à l’exécution bord2bis.log8 du programme bord2bis.adb9 .

1.2 Affectation
L’instruction d’affectation permet de donner une (nouvelle) valeur à une
variable.
Exemple :
I := 36;
P := P + Q;
Remarque. Le symbole := peut être suivi de toute expression produisant
une valeur du type de la variable à laquelle elle doit être affectée.

Une variable de type Integer peut être vue comme une boı̂te qui contient
à tout moment une valeur de type Integer.
Cette valeur peut être changée et c’est d’ailleurs le rôle de l’affectation.
Exemple :
P := I;
I := I+1;
Les variables n’ont pas le même sens selon qu’elles se trouvent à gauche
ou à droite du symbole :=.
1. une variable à gauche de l’affectation est la cible de l’affectation.
2. lorsqu’une variable apparaı̂t dans une expression à droite d’une affec-
tation, sa signification est la valeur qu’elle contient au moment où l’ex-
pression est évaluée.
Dans le langage Caml, les références sont l’équivalent des variables de
Ada. Caml interdit la confusion entre la variable I et sa valeur qui s’écrit !I.
Ainsi, les deux affectations ci-dessus s’écrive :
P := !I;
I := !I+1;

4
1.3 Les constantes
Une constante se déclare comme une variable ; il faut insérer le mot réservé
constant après le deux-points.
Exemple :

Pi : constant Float := 3.141_592_653_6;

Toute tentative d’affectation d’un tel objet sera rejetée par le compilateur.

5
Chapitre 2

Blocs et portées

Les déclarations, qui introduisent des objets, doivent précéder les instruc-
tions qui manipulent ces objets.
Rappel : Les déclarations et les instructions apparaissent dans des endroits
différents du programme. Nous parlerons de
– partie déclarative pour toute zone où il est possible de déclarer des
objets et de
– partie instructions pour une zone où il est possible d’écrire des ins-
tructions.
Exemple : Le bloc declare est une instruction qui introduit les deux types
de zones.

declare
I : Integer := 0; -- Declarations
begin
I := I + 1; -- Instructions
end;

– La partie déclarative se trouve entre declare et begin.


– La partie instructions se trouve entre begin et end.
L’exécution d’un bloc se fait en deux étapes :
– Les déclarations de sa partie déclarative sont alors élaborées, puis
– les instructions du corps sont exécutées.
Une fois atteint le end du bloc, toutes les entités déclarées dans le bloc
cessent immédiatement d’exister.

6
2.1 Portée et visibilité
Comme d’autres langages à structure de bloc, Ada possède la notion
d’occultation : la définition d’un identificateur dans une portion de pro-
gramme y cache toute éventuelle définition précédente de ce même identifi-
cateur.
Exemple : Voire bloc1.adb10 et son exécution bloc1.log11 .
Définitions :
1. La portée d’une entité est la région de texte dans laquelle l’entité est
potentiellement visible ;
2. l’entité est visible en un point si l’on peut se servir de son nom pour
s’y référer.


Il est possible de nommer un bloc. Si la déclaration d’un objet en masque
une autre, on peut se référer à l’objet masqué en utilisant (avec la notation
pointée) le nom du bloc où il est déclaré.
Voire bloc2.adb12 et son exécution bloc2.log13 .
Attention ! Dans le cas où un bloc est nommé, il est impératif de répeter
son nom après son end final.

Style : Il est conseillé de choisir un identificateur d’autant plus grand que
sa portée est grande. En effet,
– Il est dangeureux d’avoir une variable globale comme I ou X. Le risque
d’une fausse manipulation d’une telle variable est grand.
– Il est inutile de choisir un identificateur long si sa portée n’est que de
quelques lignes.

7
Notes

1
fichier : Ada/Bord/sqrt.adb

with Io;
function Sqrt (X : Natural) return Integer is
R : Natural;
begin
Io.Put ("Entrée dans Sqrt : X = "); Io.Put (X); Io.Put (". ");
R := 0;
while (R + 1) ** 2 <= X loop
R := R + 1;
end loop;
Io.Put ("Sortie de Sqrt"); Io.New_Line;
return R;
end Sqrt;

2
fichier : Ada/Bord/bord1.log

$ ./bord1
Entrée dans Sqrt : X = 2000. Sortie de Sqrt
Entrée dans Sqrt : X = 2000. Sortie de Sqrt
Entrée dans Sqrt : X = 2000. Sortie de Sqrt
A = 44
B = 44
C = 44

3
fichier : Ada/Bord/bord1.adb

with Io;
with Sqrt;
procedure Bord1 is
A, B, C : Integer := Sqrt (2000);
begin
Io.Put ("A = "); Io.Put (A); Io.New_Line;
Io.Put ("B = "); Io.Put (B); Io.New_Line;
Io.Put ("C = "); Io.Put (C); Io.New_Line;
end Bord1;

4
fichier : Ada/Bord/bord1bis.log

8
$ ./bord1bis
Entrée dans Sqrt : X = 2000. Sortie de Sqrt
A = 44
B = 44
C = 44

5
fichier : Ada/Bord/bord1bis.adb

with Io;
with Sqrt;
procedure Bord1bis is
A : Integer := Sqrt (2000);
B, C : Integer := A;
begin
Io.Put ("A = "); Io.Put (A); Io.New_Line;
Io.Put ("B = "); Io.Put (B); Io.New_Line;
Io.Put ("C = "); Io.Put (C); Io.New_Line;
end Bord1bis;

6
fichier : Ada/Bord/bord2.log

$ ./bord2
Compteur = 3
A = 44
B = 44
C = 44

7
fichier : Ada/Bord/bord2.adb

with Io;
procedure Bord2 is

function Sqrt (X : Natural) return Integer;

Compteur : Integer := 0;

function Sqrt (X : Natural) return Integer is


R : Natural;
begin
Compteur := Compteur + 1;
R := 0;

9
while (R + 1) ** 2 <= X loop
R := R + 1;
end loop;
return R;
end Sqrt;

A, B, C : Integer := Sqrt (2000);

begin
Io.Put ("Compteur = "); Io.Put (Compteur); Io.New_Line;
Io.Put ("A = "); Io.Put (A); Io.New_Line;
Io.Put ("B = "); Io.Put (B); Io.New_Line;
Io.Put ("C = "); Io.Put (C); Io.New_Line;
end Bord2;

8
fichier : Ada/Bord/bord2bis.log

$ ./bord2bis
Compteur = 1
A = 44
B = 44
C = 44

9
fichier : Ada/Bord/bord2bis.adb

with Io;
procedure Bord2bis is

function Sqrt (X : Natural) return Integer;

Compteur : Integer := 0;

function Sqrt (X : Natural) return Integer is


R : Natural;
begin
Compteur := Compteur + 1;
R := 0;
while (R + 1) ** 2 <= X loop
R := R + 1;
end loop;
return R;
end Sqrt;

10
A : Integer := Sqrt (2000);
B, C : Integer := A;

begin
Io.Put ("Compteur = "); Io.Put (Compteur); Io.New_Line;
Io.Put ("A = "); Io.Put (A); Io.New_Line;
Io.Put ("B = "); Io.Put (B); Io.New_Line;
Io.Put ("C = "); Io.Put (C); Io.New_Line;
end Bord2bis;

10
fichier : Ada/Declare/bloc1.adb

with Io;
procedure Bloc1 is
begin

declare
I, J : Integer;
begin
I := 0;
J := 1_000_000;
Io.Put (" I = "); Io.Put (I); Io.New_Line;
declare
I : Integer;
begin
I := J - 1;
Io.Put (" I = "); Io.Put (I); Io.New_Line;
I := I - 1;
Io.Put (" I = "); Io.Put (I); Io.New_Line;
end;
Io.Put (" I = "); Io.Put (I); Io.New_Line;
end;

end Bloc1;

11
fichier : Ada/Declare/bloc1.log

$ ./bloc1
I = 0
I = 999999
I = 999998
I = 0

11
12
fichier : Ada/Declare/bloc2.adb

with Io;
procedure Bloc2 is
begin
Bloc :
declare
I, J : Integer;
begin
I := 100;
J := 2 * I;
Io.Put (" I = "); Io.Put (I); Io.New_Line;
Io.Put (" J = "); Io.Put (J); Io.New_Line;
declare
I, K, L : Integer;
begin
I := 0;
K := 10 * I;
L := 10 * Bloc.I;
Io.Put (" I = "); Io.Put (I); Io.New_Line;
Io.Put (" J = "); Io.Put (J); Io.New_Line;
Io.Put (" K = "); Io.Put (K); Io.New_Line;
Io.Put (" L = "); Io.Put (L); Io.New_Line;
end;
Io.Put (" I = "); Io.Put (I); Io.New_Line;
Io.Put (" J = "); Io.Put (J); Io.New_Line;
end Bloc;

end Bloc2;

13
fichier : Ada/Declare/bloc2.log

$ ./bloc2
I = 100
J = 200
I = 0
J = 200
K = 0
L = 1000
I = 100
J = 200

12

Vous aimerez peut-être aussi