forked from meakitfed/ProjetMort
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathex1.txt
291 lines (251 loc) · 9.31 KB
/
ex1.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
object CptPoint is /* Compteur d'instances de Point */
{ var next : Integer := 1; /* index de la prochaine instance de Point */
def incr() : Integer is { result := this.next; this.next := this.next + 1;}
def howMany() : Integer := this.next - 1
}
class Point(var x: Integer, var y: Integer := 0, var name: String := "")
{ CptPoint.incr(); } is
{ var hasClone : Integer := 0; /* attributs supplementaires */
/* la valeur du champ ci-dessous est indefinie si hasClone vaut 0.
* Le probleme est qu'on n'a pas l'equivalent de NULL (du bon type)
* dans le langage. On ne peut pas utiliser un 'object' pour cela car
* un objet n'a pas de type defini.
*/
var clone : Point;
def setName(s: String) is { this.name := s; }
def getx() : Integer := this.x /* pas de this implicite */
def gety() : Integer := this.y
def cloned() : Integer := this.hasClone <> 0
def move(dx: Integer, dy: Integer, verbose: Integer := 0) : Point is {
this.x := this.x + dx; this.y := this.y + dy;
if verbose then { this.print(); } else {}
result := this;
}
def print(verbose : Integer := 0 ) is {
if verbose then "Inside Point::print".println(); else { }
/* Exemples avec l'operateur & de concatenation de chaines */
this.name.print();
( "= (" & this.x.toString() & ", " & this.y.toString() & ")" ).println();
}
/* par defaut, on ajoute un ' au nom de l'objet. On pourra le changer
* avec setName
*/
def clone() : Point is
{ this.hasClone = 1;
/* On memorise le dernier clone construit à partir de cet objet */
this.clone := new Point(this.x, this.y, this.name & "'");
result := this.clone;
}
/* imprime le clone de cet objet, s'il existe, ainsi que recursivement
* les clones de ce dernier
*/
def allClones () is {
if this.hasClone <> 0 then { this.clone.print(1); this.clone.allClones(); }
else { }
}
def egal(p: Point) : Integer is {
/* ils sont egaux s'ils ont memes coordonnees */
var b1 : Integer := p.getx() - this.x;
var b2 : Integer := p.gety() - this.y;
is
if b1 then result := 0; else result := b2 = 0;
}
def egal2(p: Point) : Integer is { /* autre version */
var b1 : Integer := p.getx() - this.x;
var b2: Integer;
is
result := 0;
if b1 then { return; } else { }
b2 := p.gety() - this.y;
result := b2 = 0;
}
}
class Couleur(var coul: Integer := 0)
/* 3 couleurs : couleur = 0, 1 ou 2
* Valeur initiale a 0 par defaut mais modifiable en passant un argument
* explicitement. Le corps du constructeur garantit qu'on a bien que
* trois couleurs.
*/
{ if this.coul < 0 then this.coul := 0;
else if this.coul > 2 then this.coul := 0; else {}
}
is
{
def name(verbose: Integer := 0) : String is {
var aux : String;
is
if verbose then "Inside Couleur::couleur".println(); else {}
if this.coul = 0 then result:= "Blanc";
else { var dummy : String; is
if this.coul = 1 then aux := "Noir"; else aux := "Gris";
result := aux;
}
}
def estGris() : Integer is {
"Inside Couleur::estGris".println();
result := this.coul = 2;
}
}
object CouleurFactory is
{ var theBlanc: Couleur := new Couleur();
var theNoir : Couleur := new Couleur(1);
var theGris : Couleur := new Couleur(2);
def blanc() : Couleur := this.theBlanc
def noir() : Couleur := this.theNoir
def gris() : Couleur := this.theGris
}
/* ci-dessous on ne met pas var devant x et y sinon ca definirait deux
* nouveaux champs qui masqueraient ceux herites de Point
*/
class PointColore(x: Integer := 0, y:Integer:= 0,
var coul: Couleur := CouleurFactory.blanc())
extends Point(x, y) is {
def couleur() : Couleur := this.coul
def colore() : Integer := this.coul.estGris() <> 0
/* pas PointColore. Pas de covariance ! On ne peut pas reutiliser le
* clone de Point car ca nous donenrait une instance de Point.
* On n'a pas le mecanisme general de Java ou SmallTalk qui permet de
* remonter jusqu'a la racine de la hierarchie tout en allouant un
* objet de la bonne classe.
*/
override def clone() : Point /* pas PointColore. Pas de covariance ! */
/* ci-dessous x et y sont les champs herites de Point */
:= new PointColore(this.x, this.y, this.coul)
def estGris() : Integer := this.coul.estGris()
/* En-tete incorrect: on ne peut pas redonner ou modifier l'expression
* d'une valeur par defaut lors d'une redefinition:
* override def print(verbose : Integer := 0)
* Ci-dessous verbose a une valeur par defaut implicite, définie dans la
* methode print de Point.
*/
override def print(verbose : Integer) is {
if verbose then "Inside PointColore::print".println(); else { }
super.print(); /* usage classique de super */
this.couleur().name().println();
}
}
class PointNoir(xc: Integer, yc:Integer)
extends PointColore(xc, yc, CouleurFactory.noir())
/* pas de corps de constructeur pour cette classe */
is {
override def estGris() : Integer := 0
override def colore() : Integer := 1
override def couleur() : Couleur := CouleurFactory.noir()
}
class DefaultPoint() /* Parentheses obligatoires */
extends PointColore(0, 0, CouleurFactory.blanc())
is {
override def estGris() : Integer := 0
override def couleur() : Couleur := CouleurFactory.blanc()
}
object Test is {
def test(p: Point, p2: PointColore, p3: PointNoir) is {
var c: String; var c2: String; var c3: String;
var true: Integer := 1;
is
p.print(true);
p2.print(true);
"Appel 1: ".println();
if p2.colore() <> 0 then c := "colore"; else c := "gris";
"Appel 2: ".println();
if p3.colore() <> 0 then c2 := "colore"; else c2 := "gris";
"Appel 3: ".println();
if p3.colore() <> 0 then c3 := "colore"; else c3 := "gris";
"Resultats de test: ".println();
c.print(); " ".print();
c2.print(); " ".print();
c3.print();
"".println(); /* imprime une ligne vide */
}
def test2(p: PointColore) is {
p.couleur().name().print();
}
}
/* des exemples ad-hoc qui montrent d'autres aspects ... */
class A() is {
var v : Integer := 1;
def f() is { "A::f()\"n".print(); }
def h(x: Integer, y : Integer := 2) : Integer := x + y
}
class A2() extends A() is {
var v : String := "hello"; /* masque le champ v de la classe A */
override def f() is { "A2::f()\"n".print(); }
def g() is {
this.v := "world"; /* par defaut, il s'agit du champ de A2 */
/* this etant caste en A, le champ v en question est celui de A */
(A this).v := 1;
/* les deux appels doivent fournir la meme chose */
this.f();
(A this).f();
}
/* ajoute une valmeur par defaut à x qui n'en avait pas. Le parametre
* y conserve sa valeur par defaut definie dans la methode de la superclasse
*/
override def h(x : Integer := 3, y: Integer) : Integer := super.h(x, y)
}
{ /* Bloc qui correspond au programme principal */
var true: Integer := 1;
var false: Integer := 0;
var p1: Point := new Point(1, 5, "p1");
var p2: Point := new Point(2, 3, "p2");
var p3 : Point := new Point(0, 0, "p3");
/* Incorrect: les types ne sont pas consideres quand on decide s'il faut
* utiliser les valeurs par defaut. Si on donne un argument, ca doit
* forcement correspondre au premier parametre, etc. Ci-dessous, on ne
* peut pas omettre les coordonnees et ne passer que la couleur !
* var err : PointColore := new PointColore(new Couleur(25));
*/
var fv : Integer := 12;
var o : PointColore := new PointColore(0, 0, CouleurFactory.blanc());
var pn : PointNoir := new PointNoir(+1, -1);
/* Incorrect: le constructeur de PointNoir n'est pas une redefinition
* du constructeur de PointColore ou de Point. Il ne beneficie donc
* pas de valeurs par defaut pour ses arguments (masi on aurait pu en
* prevoir dans sa definition)
* var pn2 : PointNoir := new PointNoir();
*/
var dp : DefaultPoint := new DefaultPoint();
var clone1: Point;
var clone2: Point;
is
"Debut du programme".println();
p1.print(0);
p2.print(0);
p2.move(p1.getx(), p1.gety(), 0);
p2.print(0);
o.print(0);
o.setName("origine");
o.print(true);
p2.move(p1.getx()-2*5-3, p1.gety(), 0);
p2.print(true);
"On va essayer le clonage:".println();
clone1 := p1.clone(); clone1.print(false);
"p1 cloned: ".print();
if p1.cloned() then "OK".println(); else "KO".println();
clone2 := clone1.clone(); clone2.move(54, 36, 0).print(false);
"Impression de tous les clones de p1:".println();
p1.allClones();
"Fin de l'impression de tous les clones".println();
/* Ne doit pas compiler car clone() renvoie statiquement un Point alors
* que o est declare comme PointColore
* o := o.clone();
*/
"Valeur du compteur de nombre de points: ".println();
CptPoint.howMany().toString().println();
p1 := p1.clone().move(+2, -3, 0);
p1.print(true);
o.clone().print(true);
"test(Point, PointColore, PointNoir)".println();
Test.test(p1, o, pn);
"test(PointNoir, PointNoir, PointNoir)".println();
Test.test(pn, pn, pn);
p1 := pn; /* affectation entre pointeurs ! */
Test.test2(o);
Test.test2(pn);
o := pn; /* Idem : on doit avoir de la liaison dynamique ci-dessous */
"test(PointNoir, PointNoir, PointNoir)".println();
Test.test(p1, o, pn);
Test.test2(o);
Test.test2(pn);
"\nDone".println();
}