-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlog1-chapitre-oo.tex
1798 lines (1570 loc) · 57.6 KB
/
log1-chapitre-oo.tex
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
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%========================
\chapter{L'orienté objet}
%=========================
\marginicon{objectif}
Dans ce chapitre, nous présentons les bases de la programmation orientée
objet. Nous commençons par expliquer les motivations qui ont amené ce
type de programmation avant d'entrer dans le vif du
sujet en explicitant le concept
d'\textit{encapsulation}. Les autres piliers de
l'orienté objet (\textit{héritage} et
\textit{polymorphisme}) ne seront pas vus cette année.
%===================
\section{Motivation}
%====================
Depuis son apparition, la puissance de l'ordinateur
n'a cessé de croitre exponentiellement. Les tâches qui
lui sont confiées ont fait de même. Ainsi les programmes à écrire sont
de plus en plus gros et de plus en plus complexes.
Face à la complexité, la démarche est toujours la même~: découper le
problème en sous-problèmes (qui peuvent à leur tour être découpés) ce
qui permet
\begin{liste}
\item
d'attaquer chaque problème séparément en évitant la
surcharge cognitive ;
\item
de répartir le travail entre plusieurs personnes ;
\item
de pouvoir réutiliser du travail déjà produit si un sous-problème est
déjà apparu dans le cadre d'un autre problème ;
\item
de produire un code plus lisible car s'exprimant avec
des termes de plus haut niveau,
plus proches du problème à résoudre.
Ainsi, là où un tri devra être fait,
on trouvera le mot «~trier~» qui fera référence
à la partie de code qui s’occupe du tri.
Cela va dans le sens d’une plus grande «~abstraction~» du code~:
un code qui s’éloigne du langage simpliste
compris par le processeur pour s’approcher de la
pensée humaine et des termes du problème à résoudre.
\end{liste}
Les langages de programmation ont suivi cette approche en permettant
toujours plus d’abstraction. Dans un chapitre précédent, on vous a
présenté la notion de module qui permet de découper la tâche à réaliser
en sous-tâches ainsi que la notion de structure qui permet de regrouper
des données. Il s'agit là de deux approches dissociées.
C'est cette lacune que se propose de combler
l'orienté objet~: permettre de définir des
\textbf{objets} (composés de \textbf{données} et
\textbf{d'instructions}) qui sont proches du problème
à résoudre. Cela va permettre une meilleure lisibilité et une plus
grande concision du code. Ainsi on pourra définir les notions de date,
d'employé, de fournisseur, de plateau de jeu, de pion,
de livre, d'emprunteur, de carte à jouer, de chambre,
de réservation, de vol, de produit, de stock, de ristourne, de facture,
de panier d'achats, de compte en banque, de banque, de
client, de portefeuille d'actions, ...
%==========================
\section{La notion d'objet}
%==========================
\subsection{Définition}
%-----------------------
\marginicon{definition}
Un \textbf{objet}%
\footnote{%
Les définitions sont tirées du livre de Cardon et
Dabancourt (cf. bibliographie)
}
est une entité logicielle qui~:
\begin{liste}
\item
a une \textbf{identité~}; c'est-à-dire que nous pouvons
identifier un objet par un nom (tout comme une variable possède un
nom).
\item
est capable de sauvegarder un \textbf{état}, c'est à
dire un ensemble d'informations dans des variables
internes;
\item
répond à des \textbf{messages} précis en déclenchant des activations
internes appropriées qui peuvent changer l'état de
l'objet. Ces opérations sont appelées des
\textbf{méthodes}. Ce sont des fonctions liées à des objets et qui
précisent le \textbf{comportement} de ces objets.
\end{liste}
\subsection{État}
%-----------------
\marginicon{definition}
Un objet contient de l'information, des données qui
définissent son état.
\textbf{Exemples}
\begin{liste}
\item
Pour un produit, l'état peut être~:
l'intitulé du produit, son code barre, son prix, ...
\item
Pour un employé, on peut avoir~: son nom, son prénom, son adresse, sa
date d'embauche, son salaire mensuel, sa fonction, son
téléphone, ...
\item
Une carte à jouer a une couleur et une valeur.
\item
L'état d'une date est le jour du
calendrier qu'elle représente.
\item
L'état d'une heure est le moment de la
journée qu'elle représente.
\end{liste}
L'état d'un objet est mémorisé via des
variables qu'on appelle des \textit{attributs}.
\subsection{Attributs}
%----------------------
\marginicon{definition}
Les \textbf{attributs} d'un objet sont
l'ensemble des informations se présentant sous forme
de variables et permettant de représenter l'état
d'un objet.
Nous verrons plus loin la syntaxe précise
pour définir les attributs d'un objet.
\textbf{Exemples}
\begin{liste}
\item
L'intitulé d'un produit peut être
représenté par une chaine. C'est également le cas des
nom(s) et prénom(s) d'un employé.
\item
La date d'embauche peut être représentée par un «~objet
date~» (une date est rarement un type primitif du langage utilisé). Un
attribut d'un objet peut être lui même un objet.
\item
Un moment de la journée peut aussi être un objet représenté par trois
entiers\footnote{Toutefois, on verra que ce n'est
peut-être pas la meilleure solution.}~: les heures, les minutes et les
secondes (en supposant qu'on désire une précision de
l'ordre de la seconde).
\item
L'adresse d'un employé peut être
représentée par une seule chaine mais également par un «~objet
adresse~» (qui contiendrait~: une rue, un numéro, un code postal\dots).
\end{liste}
\marginicon{attention}
\textbf{Remarque}\textbf{~: }Certaines parties de
l'état peuvent évoluer au fil du temps.
D'autres parties sont immuables.
Ainsi l'adresse d'une personne peut changer
mais pas sa date de naissance.
\begin{Emphase}{Exercices - attributs}
\marginicon{exercice}
\remonter
\begin{enumerate}
\item
Quel(s) attribut(s) prendriez-vous pour représenter
(l'état d') une date ?
\item
Et pour un dé à 6 faces ?
\item
Et pour un produit de magasin ?
\item
Et pour une télévision ?
(on peut en trouver vraiment beaucoup !)
\end{enumerate}
\end{Emphase}
\subsection{Comportement}
%-------------------------
\marginicon{definition}
Le \textbf{comportement} d'un objet est défini par
l'ensemble des messages ou requêtes auxquels il peut répondre.
Pour ce faire, il exécute un module qui pourra
éventuellement retourner une information à l'émetteur
du message.
Les messages peuvent interroger l'objet, le modifier,
lui demander d'agir sur son environnement (afficher du
texte, modifier un fichier\dots).
\textbf{Exemples}
\begin{liste}
\item
Quels «~messages~» peut-on envoyer à une date ?
On peut lui demander (entre autres) :
\begin{liste}
\item
des informations sur le jour du mois, le mois, l'année,
le jour de la semaine ;
\item
si elle est antérieure ou non à une autre date ;
\item
si elle fait partie d'une année bissextile ;
\item
le nombre de jours qui la sépare de la fin de l'année ;
\item
de passer au jour suivant, à la semaine suivante\dots
\end{liste}
\item
Et pour un stock de produits ? On peut
\begin{liste}
\item
lui demander la quantité disponible d'un produit donné ;
\item
lui annoncer l'arrivée d'une quantité
donnée d'un produit donné ;
\item
lui indiquer qu'un produit n'existe
plus (à retirer du stock) ;
\item
lui demander d'enlever une certaine quantité
d'un produit du stock.
\end{liste}
\item
Et pour un employé ? On peut
\begin{liste}
\item
lui demander son adresse, son salaire ou sa fonction\dots
\item
augmenter son salaire ;
\item
le changer de fonction ;
\item
le licencier
(penser à prévoir une date de départ dans l'état !).
\end{liste}
\item
Pour un moment de la journée on peut demander s'il se
situe le matin ou pas\dots
\end{liste}
\begin{Emphase}{Exercices - comportement}
\marginicon{exercice}
\remonter
\begin{enumerate}
\item
Quel comportement voyez-vous pour un téléviseur ?
\item
Et pour un produit de magasin ?
\end{enumerate}
\end{Emphase}
\subsection{Méthode}
%--------------------
\marginicon{definition}
Un message lance l'exécution d'un
module appelé \textbf{méthode} dans le jargon de
l'orienté objet.
\textbf{Exemples}
\begin{liste}
\item
Pour permettre à une date de passer au jour suivant, nous allons définir
une méthode qui incrémente le jour du mois en tenant compte
d'un possible basculement au mois suivant ou à
l'année suivante.
\item
Pour calculer le bénéfice d'un produit, nous allons définir
une méthode qui, à partir du prix d'achat et du prix de vente,
calcule le bénéfice.
\item
Pour permettre à un moment d'indiquer
s'il est le matin ou pas, nous allons définir une
méthode comme celle-ci (nous verrons plus tard comment
l'associer aux objets)
\medskip
\cadre{
\begin{pseudo}
\LComment On suppose que 'heure' est un des attributs utilisés
\LComment pour représenter l'état (le moment dans la journée)
\Method{estMatin}{}{booléen}
\Return heure < 12 \RComment on considère que midi est situé l'après-midi
\EndMethod
\end{pseudo}
}
\medskip
Cet exemple devrait vous sembler familier à deux exceptions près
\begin{liste}
\item
on utilise le mot «~\textstyleMotCl{méthode}~» en lieu et place de
«~\textstyleMotCl{module}~» ;
\item
les attributs (l'heure ici) ne sont pas passés en
paramètre. Un objet connait déjà son état et donc la valeur de ses
attributs. Nous verrons plus loin la syntaxe précise.
\end{liste}
\end{liste}
\begin{Emphase}{Exercices - méthodes}
\remonter
\marginicon{exercice}
\begin{enumerate}
\item
Dans le comportement d'un téléviseur, on retrouve
«~éteindre~» et «~allumer~».
À quoi ressemblerait le code de ces méthodes ?
\item
Écrivez la méthode qui permet de passer au jour suivant.
\item
Écrivez la méthode qui calcule
le bénéfice réalisé lors de la vente d'un produit.
\end{enumerate}
\end{Emphase}
\subsection{Activer un comportement}
Pour activer un comportement d'un objet,
il faut lui envoyer un message
(ou dit autrement, appeler une de ses méthodes).
La syntaxe que nous allons utiliser
(c'est la plus courante) est la notation pointée.
\cadre{
\begin{pseudo}
\Stmt nomObjet.nomMéthode()
\end{pseudo}
}
\medskip\textbf{Exemple}~:
Supposons que le nom «~maintenant~»
désigne un objet contenant un moment de la journée
(on verra comment réaliser cela).
Si on veut savoir si on est le matin, on peut écrire
\cadre{
\begin{pseudo}
\If{maintenant.estMatin()}
\Stmt ...
\EndIf
\end{pseudo}
}
\begin{Emphase}{Exercice – activer un comportement}
\marginicon{exercice}
Écrire la portion de code qui allume une télévision
(désignée par «~maTélévision~»)
et puis l'éteint aussitôt après.
\end{Emphase}
\subsection{Les paramètres d'un comportement}
Activer un comportement revient à appeler une méthode de
l'objet. Souvent il est nécessaire
d'envoyer à l'objet des informations
complémentaires pour préciser notre demande ce qui se fait via
l'utilisation des paramètres.
\textbf{Exemple}~:
Si on veut modifier le salaire d'un employé,
il faut que notre message contienne le nouveau salaire.
Autrement dit,
il faut communiquer ce nouveau salaire à la méthode
de changement du salaire.
Ce qui donne la méthode suivante~:
\cadre{
\begin{pseudo}
\Method{modifierSalaire}{nouveauSalaire~: entier}{}
\Stmt salaire \Gets nouveauSalaire
\EndMethod
\end{pseudo}
}
\begin{Emphase}{Exercices – paramètres du comportement}
\remonter
\marginicon{exercice}
\begin{enumerate}
\item
Prenons un objet représentant un produit de magasin.
Nous supposerons qu'un produit a un \textit{numéro},
un \textit{libellé}, un \textit{prixAchat},
un \textit{prix de vente} et une \textit{quantitéEnStock}
Donnez les \textbf{entêtes} des méthodes suivantes
qui permettent de~:
\begin{liste}
\item
obtenir le prix de vente
\item
calculer le bénéfice
\item
donner la quantité restant en stock
\item
dire si le produit est en rupture de stock.
\end{liste}
\item
Prenons un objet représentant une date du calendrier grégorien.
Donnez les entêtes des méthodes suivantes qui permettent de~:
\begin{liste}
\item
demander le nom du jour correspondant à une date (par exemple lundi, mardi, ...)
\item
savoir si une date est antérieure à une autre
\item
connaitre le nombre de jours (absolu) séparant deux dates.
\end{liste}
\item
Utilisation. Soit deux dates $date1$ et $date2$ ; écrivez la
portion de code qui utilise les méthodes ci-dessus pour
\begin{liste}
\item
vérifier quelle date précède l'autre;
\item
calculer le nombre de jours d'écart entre ces deux
dates.
\end{liste}
\item
Précédemment, vous avez défini l'ensemble du
comportement d'un téléviseur. Écrivez les entêtes des
méthodes correspondant à ce comportement ainsi qu'une
portion de code qui les utilise.
\end{enumerate}
\end{Emphase}
%=========================
\section{L'encapsulation}
%=========================
Un objet possède un état qui est représenté par des attributs.
Les bonnes pratiques de la programmation orientée objet préconisent
fortement que les attributs d'un objet soient
invisibles en dehors de l'objet.
Ils ne pourront être accédés qu'au travers
du comportement de l'objet,
c'est-à-dire via ses méthodes.
\marginicon{definition}
\textbf{%
Lorsque les détails de l'implémentation
d'un objet sont masqués aux autres objets, on dit
qu'il y a \textbf{encapsulation} des données et du
comportement des objets.
}
Pourquoi une telle recommandation ?
Le but est de garantir la cohérence de l'état de l'objet.
Si on pouvait accéder directement à un attribut
(et donc le modifier),
on pourrait y mettre une valeur incohérente.
Par exemple, on pourrait dire que les minutes d'un moment
valent -3 ou 75 ou encore que le jour d'une date est 32 !
Dès lors, il nous faudra préciser pour chaque \textbf{membre}
(attributs et méthodes) d'un objet s'il est
\textbf{privé} (inconnu de l'extérieur) ou
\textbf{public} (connu de l'extérieur).
Le bon usage impose que tous les attributs soient rendus privés
et que les méthodes restent publiques.
Toutefois, on pourra trouver également des méthodes privées.
Ce sera notamment le cas si plusieurs méthodes d'un objet
ont une partie commune ;
il sera intéressant de la \textit{factoriser},
c-à-d en faire une méthode privée (ex~: un calcul de maximum).
Puisqu'un attribut est privé,
il est courant pour chacun des attributs de rencontrer
une méthode destinée à connaitre la valeur de cet attribut
et une autre qui permet de la modifier.
\subsection{Accesseur et mutateur}
%----------------------------------
\marginicon{definition}
\textbf{Accesseur}%
\footnote{On utilise aussi souvent le mot anglais «~getter~».}%
~: méthode dont le but est de fournir la valeur d'un attribut.
\textbf{Mutateur}%
\footnote{On utilise aussi souvent le mot anglais «~setter~»}%
~: méthode dont le but est de modifier la valeur d'un attribut.
Par convention,
ces méthodes sont nommées \code{getNom} et
\code{setNom} où «~nom~» est le nom de l'attribut%
\footnote{%
Pour un attribut booléen,
on pourra préférer \code{estNom} ou \code{isNom}
au lieu de \code{getNom}.
}
Par facilité, on utilisera parfois le terme «~accesseur~»
pour désigner à la fois les «~accesseurs~» et les «~mutateurs~».
\textbf{Exemple}~:
Écrivons l'accesseur et le mutateur pour l'attribut
«~heure~» d'un moment de la journée.
\cadre{
\begin{pseudo}
\Method{getHeure}{}{entier}
\Return heure
\EndMethod
\end{pseudo}
}
\cadre{
\begin{pseudo}
\Method{setHeure}{uneHeure~: entier}{}
\Stmt heure \Gets uneHeure
\EndMethod
\end{pseudo}
}
\subsection{Que faire si le paramètre est invalide ?}
%-----------------------------------------------------
Dans l'exemple précédent,
que se passerait-il si le paramètre \code{uneHeure} vaut 25 ?
Une valeur aberrante serait affectée à l'attribut \code{heure}.
Dans le cas de paramètres invalides,
la plus mauvaise solution est de ne rien faire.
Le programme continuerait en croyant que tout s’est bien
passé et il court à la catastrophe.
Il est préférable qu’un programme s'interrompe
plutôt que de fournir une mauvaise réponse.
Dans certains langages (comme le C),
l’usage est que chaque module retourne un entier indiquant
s'il y a eu une erreur (et laquelle).
L’inconvénient est que le module appelant n’est pas
obligé de tenir compte de l’erreur.
Les \textbf{exceptions} sont un mécanisme du même genre
mais qui oblige à fournir un code de traitement de l’erreur.
Il ne sera pas étudié en première année%
\footnote{%
En tout cas pas au cours de Logique
mais vous étudierez cette notion au cours de Java.%
}.
Cette année, nous nous contenterons d'indiquer
clairement dans nos codes qu'il s'agit d'une situation anormale
via la primitive \code{erreur} qui arrête le déroulement du
programme avec une courte explication du problème.
La syntaxe que nous allons retenir est
\cadre{
\begin{pseudo}
\Stmt \K{erreur} "explication de l'erreur"
\end{pseudo}
}
Ce qui donne~:
\cadre{
\begin{pseudo}
\Method{setHeure}{uneHeure~: entier}{}
\If{uneHeure < 0 OU uneHeure > 23}
\Stmt \K{erreur} "heure invalide"
\EndIf
\Stmt heure \Gets uneHeure
\EndMethod
\end{pseudo}
}
\medskip
\textbf{Remarque}~:
Accéder à la valeur d’un attribut ne pose pas
de problème de validité.
Alors pourquoi rendre l’attribut complètement privé
plutôt que de n’empêcher que des modifications directes
(une sorte d’attribut en \textit{lecture seule}) ?
Cela permet de changer de façon transparente la représentation des données.
Nous y reviendrons plus loin.
\begin{Emphase}{Exercice - encapsulation}
\marginicon{exercice}
Sans le savoir, vous avez déjà défini des accesseurs et des
mutateurs pour le téléviseur.
Lesquels ?
En suivant la convention de nom pour les accesseurs et les mutateurs,
quels noms auraient-ils dû porter ?
\end{Emphase}
%====================================================
\section{La notion de classe et d'instance}
%=====================================================
Pour pouvoir utiliser des objets nous allons devoir les définir
(expliciter leur état et leur comportement).
Cette définition est commune à tous les objets similaires.
Par exemple tous les moments ont un même comportement
et un même type d'état
(des heures, des minutes et des secondes).
\marginicon{definition}
\textbf{Une \textbf{classe} est un ensemble d'objets qui ont en
commun les mêmes méthodes et qui partagent les mêmes types
d'attributs.}
Une \textbf{instance}%
\footnote{%
Vous pouvez considérer les termes
«~instance de classe~» et «~objet~» comme synonymes.
}
d'une classe est un objet particulier
d'une classe qui peut activer les méthodes de la
classe et qui a des valeurs particulières pour ses attributs.
On peut établir le parallélisme avec les types de base que vous avez
déjà vus. Définir une classe revient à définir un nouveau type de
données. En gros, on peut dire qu'un \textbf{objet
est à une classe ce qu'une variable est à un type}.
Comprenons bien que les objets d'une même classe ont le
même «~type~» d'état mais pas le même état proprement
dit. Deux objets «~moment~» représentent tous deux un moment
(heures, minutes, secondes) de la journée mais pas (forcement)
le même ! Ils auront donc les mêmes attributs mais
avec des valeurs différentes !
\subsection{Définition d'une classe}
%------------------------------------
Nous devons d'abord définir une classe avant de pouvoir
en instancier les objets que nous voulons utiliser. Précisons la
syntaxe utilisée pour définir une classe
\cadre{
\begin{pseudo}
\Class{NomDeLaClasse}
\Private
\LComment liste des attributs (donc privés par convention)
\Public
\LComment liste des méthodes publiques
\Private
\LComment liste des méthodes privées
\EndClass
\LComment Par souci de lisibilité, on pourra indiquer uniquement
les signatures des
\LComment méthodes et donner le code complet des méthodes à
la suite de la classe.
\end{pseudo}
}
\textbf{Exemple}~:
la classe Moment qui représente un moment de la journée.
\cadre{
\begin{pseudo}
\Class{Moment}
\Private
\Decl heure~: entier
\Decl minute~: entier
\Decl seconde~: entier
\Public
\MethodSign{getHeure}{}{entier}
\MethodSign{getMinute}{}{entier}
\MethodSign{getSeconde}{}{entier}
\MethodSign{setHeure}{uneHeure~: entier}{}
\MethodSign{setMinute}{uneMinute~: entier}{}
\MethodSign{setSeconde}{uneSeconde~: entier}{}
\MethodSign{estMatin}{}{booléen}
\EndClass
\Method{estMatin}{}{booléen}
\Return heure < 12
\EndMethod
\LComment + les accesseurs et les mutateurs
\end{pseudo}
}
\subsection{Instanciation d'une classe}
%---------------------------------------
«~Instancier~» signifie créer un objet d'une classe.
Cela s'écrit avec l'instruction
\code{nouveau}.
Pour lui donner un nom,
on l'assigne à une variable déclarée du type de la
classe.
\cadre{
\begin{pseudo}
\Decl nomObjet~: nomClasse
\RComment déclaration de l'objet
\Let nomObjet \Gets \K{nouveau} nomClasse()
\RComment instanciation de l'objet
\end{pseudo}
}
Dans ce cours de Logique, nous adopterons le fait que
les noms des paramètres soient différents de ceux des
attributs (on préconisera d’imaginer des noms variés tels
que uneDate, maDate, laListe, autreObjet…), ce qui évitera
toute ambigüité (entre minuscule et majuscule par exemple).
\textbf{Exemple}~: pour créer un moment de la journée.
\cadre{
\begin{pseudo}
\Module{test}{}{}
\Decl midi~: Moment
\RComment déclaration
\Let midi \Gets \K{nouveau} Moment()
\RComment instanciation
\Stmt midi.setHeure( 12 )
\RComment mutateur
\Stmt midi.setMinute( 0 )
\RComment " "
\Stmt midi.setSeconde( 0 )
\RComment " "
\If{midi.estMatin()}
\Write "Midi est considéré comme
étant encore le matin"
\Else
\Write "Midi est considéré comme
étant l'après-midi"
\EndIf
\EndModule
\end{pseudo}
}
Remarquez qu'il y a une différence importante entre les
objets et les types de bases. Lorsqu'on déclare une
variable d'un type de base, cela alloue
automatiquement un espace mémoire pour cette variable.
C'est différent avec les objets. La déclaration
n'entraine qu'une réservation mémoire
pour une «~référence~» vers un objet. Celui-ci
n'existe pas encore. Il sera créé (et sa mémoire
allouée) via une instruction spécifique (\code{nouveau}). On
parle de variable «\textit{~dynamique~}». Le nom est alors~une
«~référence~» vers l’objet. Les avantages de cette dissociation seront
évidents lorsque nous parlerons de la notion de \textit{constructeur}.
Après la déclaration, on a~:
\begin{center}
\begin{tabular}{m{2.2089999cm}}
\centering\arraybslash midi\\\hline
\multicolumn{1}{|m{2.2089999cm}|}{\centering\arraybslash
\itshape rien}\\\hline
\end{tabular}
\end{center}
Après l'instanciation (ou création), on a~:
\begin{center}
\begin{tabular}{m{2.578cm}m{2.261cm}|m{3.162cm}|}
\centering midi &
\multicolumn{1}{m{2.261cm}}{~
} &
\multicolumn{1}{m{3.162cm}}{\centering\arraybslash
Moment}\\\hhline{-~-}
\multicolumn{1}{|m{2.578cm}|}{~
} &
\centering \sffamily → &
\centering\arraybslash heure = ?\\\hhline{-~~}
~
&
~
&
\centering\arraybslash minute = ?\\
~
&
~
&
\centering\arraybslash seconde = ?\\\hhline{~~-}
\end{tabular}
\end{center}
Remarquez qu'il n'y a pas d'initialisation par défaut, pour le moment.
Après l'action des mutateurs, on a~:
\begin{center}
\begin{tabular}{m{2.578cm}m{2.261cm}|m{3.162cm}|}
\centering midi &
\multicolumn{1}{m{2.261cm}}{~
} &
\multicolumn{1}{m{3.162cm}}{\centering\arraybslash
Moment}\\\hhline{-~-}
\multicolumn{1}{|m{2.578cm}|}{~
} &
\centering \sffamily → &
\centering\arraybslash heure = 12\\\hhline{-~~}
~
&
~
&
\centering\arraybslash minute = 0\\
~
&
~
&
\centering\arraybslash seconde = 0\\\hhline{~~-}
\end{tabular}
\end{center}
\begin{Emphase}{Exercices – classe et instance}
\remonter
\marginicon{exercice}
\begin{enumerate}
\item
Pour les produits, vous avez déjà écrit les attributs et les en-têtes des
méthodes. Regroupez le tout en une classe \code{Produit}
\textbf{en respectant les notations que vous venez de voir.}
\item
Écrivez un module qui affiche le prix d'achat d'un produit, son prix
de vente hors TVA et son prix de vente TVA comprise.
\end{enumerate}
\end{Emphase}
%==========================
\section{Les constructeurs}
%===========================
L'encapsulation nous permet de contrôler
l'état de l'objet et de
l'empêcher de tomber dans un état invalide. Mais
qu'en est-il de l'état de départ ?
Est-il valide ?
Il serait bon, lorsqu'on crée un objet (via
\code{nouveau}) de pouvoir indiquer l'état
initial de l'objet et que cet état puisse être validé.
C'est le rôle précis des constructeurs.
\marginicon{definition}
Un \textbf{constructeur} est une méthode particulière permettant
d'initialiser les attributs d'un
objet lors de sa création effective. Elle porte le même nom que sa
classe et ne retourne pas de valeur.
Il peut y avoir plusieurs constructeurs ce qui permet
d'offrir plusieurs possibilités d'indiquer l'état initial de
l'objet. Toutefois, nous limiterons au maximum le nombre
de constructeurs dans une classe.
Remarquez que cela demande de définir plusieurs méthodes
qui portent le même nom. C'est ce qu'on appelle la
\textbf{surcharge}. Des méthodes homonymes (c-à-d de même nom) doivent
pouvoir être différenciées via leur signature (la liste de leurs
paramètres).
\textbf{Exemple}~:
Écrivons des constructeurs pour un moment de la journée~:
\cadre{
\begin{pseudo}
\Class{Moment}
\Private
\LComment pas de changement
\Decl heure~: entier
\Decl minute~: entier
\Decl seconde~: entier
\Public
\ConstrSign{Moment}{uneHeure, uneMinute, uneSeconde~: entiers}
\ConstrSign{Moment}{uneHeure, uneMinute~: entiers}
\RComment 0 seconde par défaut
\ConstrSign{Moment}{uneHeure~: entier}
\RComment initialiser à une heure pile
\Empty
\LComment pas de changement au niveau des méthodes~:
\MethodSign{getHeure}{}{entier}
\MethodSign{getMinute}{}{entier}
\MethodSign{getSeconde}{}{entier}
\MethodSign{setHeure}{uneHeure~: entier}{}
\MethodSign{setMinute}{uneMinute~: entier}{}
\MethodSign{setSeconde}{uneSeconde~: entier}{}
\MethodSign{estMatin}{}{booléen}
\EndClass
\end{pseudo}
}
\cadre{
\begin{pseudo}
\Constr{Moment}{uneHeure, uneMinute, uneSeconde~: entiers}
\Stmt setHeure(uneHeure)
\Stmt setMinute(uneMinute)
\Stmt setSeconde(uneSeconde)
\EndConstr
\Empty
\Constr{Moment}{uneHeure, uneMinute~: entiers}
\Stmt setHeure(uneHeure)
\Stmt setMinute(uneMinute)
\Stmt setSeconde(0)
\EndConstr
\Empty
\Constr{Moment}{uneHeure~: entier}
\Stmt setHeure(uneHeure)
\Stmt setMinute(0)
\Stmt setSeconde(0)
\EndConstr
\Empty
\LComment + les accesseurs, les mutateurs et les autres méthodes
\end{pseudo}
}
Contrairement à ce qu'on peut trouver dans certains langages,
comme Java par exemple, nous n'autorisons pas ici d'appel
d'un constructeur d'une classe \code{A} dans un autre constructeur
de cette même classe \code{A}.
Par contre, il est courant en logique qu'un constructeur
appelle les mutateurs afin d'effectuer les tests sans
avoir à les dupliquer.
Mais c'est une démarche que vous éviterez de faire dans
des langages comme Java par exemple
(cela vous sera expliqué plus tard).
Lorsqu'on instancie un objet, les paramètres
qu'on donne déterminent le constructeur qui est
effectivement utilisé pour initialiser l'état de
l'objet.
\textbf{Exemple}~: Instancions quelques moments de la journée.
\cadre{
\begin{pseudo}
\Let heureDépart \Gets \K{nouveau} Moment(14, 23, 56)
\Let heureLever \Gets \K{nouveau} Moment(9, 30)
\Let heureGouter \Gets \K{nouveau} Moment(17)
\end{pseudo}
}
Le fait qu'un objet est instancié via la primitive
\code{nouveau} et pas implicitement à la déclaration permet de
postposer sa construction effective au moment où
l'état initial qu'on veut lui donner
sera connu (ce qui peut résulter d'un calcul). On est
ainsi assuré que tous les objets manipulés sont valides ce qui permet
d’éviter les situations où une méthode fait des dégâts suite à la
manipulation d’un objet invalide.
\begin{Emphase}{Exercices - constructeur}
\remonter
\marginicon{exercice}
\begin{enumerate}
\item {
Écrivez un ou des constructeur(s) pour un \code{Produit}}
\item {
Adaptez le module écrit plus haut pour qu'il affiche le prix hors TVA
puis le prix TVA comprise du produit n°105176 (Lego réveil figurine policier)
au prix d'achat de 25\texteuro, au prix de vente de 30\texteuro et
dont il y a 10 exemplaires en stock.}
\end{enumerate}
\end{Emphase}
%================================================
\section{Du choix de la représentation de l'état}
%=================================================
Lorsqu'on définit une classe, il faut choisir les
attributs qui vont permettre de représenter l'état des
objets. Cela peut paraitre immédiat mais il n'en est
rien.
\textbf{Exemple}
Pour un moment de la journée, nous avons choisi
d'utiliser trois attributs entiers (les heures, les
minutes et les secondes). Nous aurions tout aussi bien pu choisir
d'utiliser un seul entier représentant le nombre de
secondes écoulées depuis minuit.
Ces deux représentations sont tout-à-fait équivalentes en terme de
potentiel mais la grande différence est l'efficacité
du code des méthodes.
Prenons deux méthodes symptomatiques~: celle qui donne
l'heure et celle qui compare deux moments de la
journée. La première est beaucoup plus simple à écrire et plus rapide
avec la première représentation alors que la seconde méthode est plus
simple à écrire et plus rapide avec la seconde représentation.
Dès lors, quelle représentation choisir ? Il faut examiner, pour chaque