58
Chapitre 3 Cours B4 : Programmation et Développement OO 1/58 Diapositive 1 Version 1.0 Programmation et Développement orientés objets Cours B4 Chapitre 3: Classes et Objets

Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Embed Size (px)

Citation preview

Page 1: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 1/58

Diapositive 1

Version 1.0

Programmation et Développement orientés objets

Cours B4Chapitre 3: Classes et Objets

Page 2: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 2/58

Diapositive 2

25/03/2001 Cours B4: Programmation et développement orientés objets 2/42

Nature d’un objetQu’est qui est objet ou qui ne l’est pas?

une chose palpable et/ou visibleQuelque chose qui peut être appréhendé intellectuellementExiste dans le temps et l’espace

Un objet a un état, un comportement et une identité

La structure et le comportement d’objets similaires sont définis dans leur classe commune

L'ingénieur et l'artiste doivent tous deux être intimement familiers avec les matériaux de leur métier. Quand nous utilisons des méthodes orientées objets pour analyser ou concevoir des logiciels complexes, les blocs de construction de base sont les classes et les objets. Puisque nous avons jusqu'ici donné seulement des définitions informelles de ces deux éléments, nous nous tournerons dans ce chapitre vers une étude détaillée de la nature des classes, des objets et de leurs relations ; en chemin, nous présenterons des lignes de conduite à adopter pour fabriquer adroitement des abstractions et des mécanismes de qualité. Définition informelle Qu’est qui est objet ou qui ne l’est pas? Nous ajoutons à notre définition informelle l'idée qu'un objet modélise une partie de la réalité et, par conséquent, existe dans le temps et l'espace. Les objets du monde réel ne sont pas les seuls qui nous intéressent pendant le développement de logiciels. D'autres genres importants d'objets sont des résultats du processus de conception, dont les collaborations avec d'autres objets similaires servent comme mécanismes pour offrir un certain comportement de haut niveau. Une définition plus précise est: un objet représente un élément particulier identifiable, unité ou entité, soit réel, soit abstrait, avec un rôle bien défini dans le domaine du problème Exemple une usine peut être décomposé en atelier, les atelier en cellules, etc… chaque atelier représente à un rôle (mécanique, chimie, …)

Page 3: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 3/58

Chacune des choses tangibles que nous avons mentionnées jusqu'ici est un objet qui à une limite clairement définie qui le sépare des autres objets. Certains objets peuvent avoir des limites conceptuelles nettes, et cependant représenter des événements ou des traitements impalpables: Considérons un système de CFAO pour modéliser des solides. Deux solides tels qu'une sphère et un cube qui se coupent peuvent former une ligne d'intersection irrégulière. Bien qu'elle n'existe pas sans la sphère ni le cube, cette ligne est encore un objet ayant des limites conceptuelles nettement définies. Le cas d’un traitement chimique est un autre exemple. Certains objets peuvent être tangibles, et cependant avoir des limites physiques floues. Des objets comme les rivières, le brouillard et la foule vérifient cette définition. (ceci n’est vrai qu’a un certain niveau d’abstraction: pour des personnes marchant dans le brouillard, la distinction entre « mon brouillard » et « son brouillard » n’est pas utile, pour un système météo le brouillard sur Paris et le brouillard sur Marseille sont deux objets différents). Attention, tout n’est pas objet: Le temps, la beauté et la couleur ne sont peut être pas des objets, mais plutôt des attributs des objets-> un homme (un objet) aime une femme (un autre objet). Un char a le poil gris Ceci amène la deuxième définition.

Page 4: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 4/58

Diapositive 3

25/03/2001 Cours B4: Programmation et développement orientés objets 3/42

Etat d’un objetL'état d'un objet englobe toutes les propriétés (habituellement statiques) de l'objet, plus les valeurs courantes (généralement dynamiques) de chacune de ces propriétés.Conseil:

Encapsuler l’état d’un objet

Un distributeur de boissons. Le comportement habituel de ces objets est que, quand on met des pièces dans une fente et qu’on appuie sur un bouton pour faire un choix, une boisson sort de la machine. Que se passe-t-il si un utilisateur fait d'abord son choix puis met l'argent dans la fente ? La plupart des distributeurs attendent simplement sans rien faire, parce que l'utilisateur a violé les hypothèses de base de leur fonctionnement. Autrement dit, le distributeur de boissons jouait un rôle (attente des pièces) que l'utilisateur a ignoré (en faisant d'abord son choix). De même, supposez que l'utilisateur ignore l'avertissement lumineux disant «appoint seulement», et mette trop d'argent. La plupart des machines sont malhonnêtes; elles avaleront gaiement les pièces en trop. Dans chacune de ces circonstances, nous voyons comment le comportement d'un objet est influencé par son histoire; l'ordre des opérations que l'on applique à un objet est important. La raison de ce comportement, dépendant du temps et des événements, est l'existence d'un état interne de l'objet. D’où la définition L’état d’un objet…. Une propriété est une caractéristique naturelle ou discriminante, un trait, une qualité ou une particularité qui contribue à rendre un objet unique. Par exemple -<un distributeur de boisson accepte de l’argent. Ces propriétés sont « habituellement » statique car elles sont fondamentales à l’objet et ne varie pas dans le temps mais … pour certain objets elles peuvent varier dans le temps -> cas des systèmes d’auto-apprentissage: Par exemple, considérons un robot autonome qui peut apprendre son environnement. Il peut d'abord reconnaître un objet qui semble être une barrière fixe puis, plus tard seulement, reconnaître que cet objet est une porte qui peut être ouverte. Dans ce cas,

Page 5: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 5/58

l'objet créé par le robot, pendant qu'il construit son modèle conceptuel, acquiert des propriétés nouvelles, au fur et à mesure que sa perception du monde s'étend. La quantité de pièces acceptées à chaque instant représente la valeur dynamique de la propriété fondamentale qu’un distributeur de boisson accepte de l’argent » et varie selon les opérations appliquées à la machine. Cette quantité augmente quand un utilisateur met de l'argent, et décroît quand un vendeur vide la machine. Notre définition indique que ces valeurs sont «habituellement dynamiques» parce que, dans certains cas, elles sont statiques. Par exemple, le numéro de série d'un distributeur est une propriété statique ayant une valeur statique. Toutes les proipriétés ont une valeur qui peut être une simple quantité ou un autre objet-> le montant introduit dans le distributeur est une valeur simple, les boissons disponibles sont des objets. On différencie les objets et les valeurs simples: Les valeurs simples sont «intemporelles, non modifiables et non instanciées» Les objets «existent dans le temps, sont modifiables, ont un état, sont instanciés et peuvent être créés, détruits et partagés».

Page 6: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 6/58

Diapositive 4

25/03/2001 Cours B4: Programmation et développement orientés objets 4/42

Exemplestruct PersonnelRecord {

char nom[100];

int numeroSS;

char service[10]

float salaire;

};

class PersonnelRecord {

public:

char* NomDeEmploye()const;

int NumeroSSEmploye()const;

char* ServiceEmploye()const;

protected:

char _nom[100];

int _numeroSS;

char _service[10];

float _salaire;

};

Chaque élément de cette structure désigne une propriété particulière de l'abstraction. Cette déclaration dénote une classe, pas un objet, parce qu'elle ne représente pas une instance spécifique. Pour déclarer des objets de cette classe, nous devons écrire PersonnelRecord Pierre, Paul, Jacques; Cette déclaration désigne une structure C++, dont la sémantique est identique à celle d'une classe dont tous les membres seraient publics. Les structures désignent donc des abstractions non encapsulées. Il vaut toujours mieux encapsuler l'état d'un objet plutôt que de l'exposer comme dans la déclaration précédente. La deuxième déclaration parait légèrement plus compliquée que la précédente, mais elle lui est largement supérieure pour plusieurs raisons. Spécifiquement, nous avons écrit cette classe de telle sorte que sa représentation soit cachée de tous les autres clients. Si nous changeons sa structure, nous pouvons avoir à recompiler du code mais, sémantiquement, aucun client ne sera affecté par ce changement (en d'autres termes, le code existant ne sera pas cassé). De plus, nous avons capté nos décisions de conception relatives à l'espace du problème en statuant explicitement sur les opérations que nous pouvons effectuer sur les objets de cette classe. En particulier, nous accordons à tous les clients le droit de retrouver le nom, le numéro de sécurité sociale et le département d'un employé. Seuls des clients spéciaux (la classe et ses sous-classes) ont la permission de modifier la valeur de ces propriétés. De plus, seuls ces clients peuvent lire ou altérer le salaire d'un employé, tandis que les clients normaux ne le peuvent pas.

Page 7: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 7/58

Une autre raison pour laquelle cette déclaration est meilleure que 1a précédente concerne la réutilisation. l'héritage nous permet de réutiliser cette abstraction et de l'affiner ou la spécialiser de différentes façons. Cependant, l'encapsulation de l'état d'un objet est un début, mais ne suffit pas â représenter toute la signification des objets que nous créons et découvrons durant un développement. Nous devons aussi prendre en compte le comportement des objets.

Page 8: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 8/58

Diapositive 5

25/03/2001 Cours B4: Programmation et développement orientés objets 5/42

Le comportement d’un objetLe comportement est la façon dont un objet agit et réagit, en termes de changement d'état et de transmission de messages.le comportement d'un objet représente ses activités externes, visibles et pouvant être testées.Affinement des état d’un objet:

L'état d'un objet représente les effets cumulés de son comportement.

Aucun objet n'existe isolément. Au lieu de cela, on agit sur des objets, et eux-mêmes agissent sur d'autres Une opération est une certaine action qu'un objet effectue sur un autre pour provoquer une réaction. Par exemple, un client pourrait invoquer les opérations append et pop respectivement pour agrandir et rétrécir un objet file d'attente. Un client pourrait aussi invoquer l'opération 1ength, qui renvoie une valeur donnant la taille de l'objet file, mais n'altère pas son état. Dans les langages à objet pur, appeler une opération s’appelle: envoyer un message (en c++ on dit plutôt appeler une fonction membre). Dans les langages à objets une opération s’appelle une méthode, en C++ on dit plutôt une fonction membre. La transmission de messages est une partie de la definition comportement d'un objet. L'état d'un objet influence aussi son comportement. Reprenons l'exemple du distributeur de boissons. Nous pouvons déclencher une action pour réaliser notre sélection, mais le comportement de la machine dépendra de son état. Si nous n'avons pas introduit suffisamment d'argent, elle ne fera probablement rien. Si nous avons mis assez d'argent, la machine l'encaissera et nous servira une boisson (modifiant ainsi son état). Nous pouvons donc dire que le comportement d'un objet est fonction de son état autant que de l'opération invoquée, certaines ayant pour effet de bord d'altérer l'état de l'objet La majorité des objets intéressants n'ont pas d'état statique. Ils contiennent plus souvent des propriétés dont les valeurs sont lues et modifiées en fonction des actions sur ceux-ci.

Page 9: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 9/58

Diapositive 6

25/03/2001 Cours B4: Programmation et développement orientés objets 6/42

Exemple d’opérations d’un objet

class Queue {

public:

Queue();

Queue(const Queue&);

virtual ~Queue();

virtual Queue& operator=(const Queue&);

virtual int operator==(const Queue&) const;int operator !=(const Queue&) const;

virtual void clear();

virtual void append(const void *);

virtual void pop();

virtual void remove(int at);

virtual int length() const;

virtual int isEmpty() const;

virtual int location(const void*);

protected...

};

Cette classe exploite l'idiome C courant de lecture et modification d'éléments via des void*. Elle offre ainsi l'abstraction d'une file hétérogène: un client peut y insérer des objets de types quelconques. Cette approche n'est pas robuste du point de vue typage, car le client doit se rappeler les types des objets qu'il a insérés dans la file. De plus, l'utilisation de void* empêche l'objet Queue de «posséder» ses éléments. Cela signifie que nous ne pouvons nous reposer sur la destruction des éléments de la file par son destructeur (--Queue () ). La déclaration de Queue représente une classe, et non un objet. Nous devons créer des instances que les clients pourront manipuler Queue a, b, c, d; Nous pouvons aussi agir sur ces objets, comme ci-dessous a.append(&Pierre); a.append(&Paul); append (&Jacques); b = a; a.pop(); Après exécution de ces instructions, la file désignée par a contiendra deux éléments (avec Paul entête), et celle désignée par b en contiendra trois (avec Pierre entête). Ainsi, chaque objet incarne un état distinct, et celui-ci affecte son comportement futur: Par exemple, nous pouvons encore dépiler trois éléments de b, mais deux seulement de a.

Page 10: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 10/58

Diapositive 7

25/03/2001 Cours B4: Programmation et développement orientés objets 7/42

Les types d’opérations5 types d’opérations

Modificateur: opération qui altère l’état de l’objetSélecteur: une opération qui accède à l’état de l’objet mais ne le modifie pasItérateur: une opération qui permet d’accéder à toutes les parties d’une objet dans un ordre définiConstructeur: opération qui crée un objet et/ou initialise son étatDestructeur: opération qui libère l’état de l’objet et/ou détruit l’objet

Utilitaires de classe

Une opération désigne un service qu'une classe offre à ses clients. En pratique, nous avons constaté qu'un client effectuait typiquement cinq sortes d'opérations sur un objet. Les trois plus courantes sont Modificateur, Sélecteur Itérateur. Parce que ces opérations sont logiquement très différentes, il est utile d'appliquer un style de codage qui met l'accent sur leurs différences. Dans la déclaration de la classe Queue, nous déclarons d'abord tous les modificateurs comme des fonctions membres non constantes (les opérations clear, append, pop, et remove), puis tous les sélecteurs comme des fonctions constantes (les opérations length, isEmpty, Location). Nous verrons plus tard que les itérateurs sont basés sur une classe séparée; En C++, les constructeurs et les destructeurs sont déclarés comme une partie de la définition d'une classe (membres Queue et -Queue). En Smalltalk et en CLOS, de telles opérations font typiquement partie du protocole d'une méta-classe (c'est-à-dire la classe d'une classe). Utilitaires de classe Avec les langages orientés objets purs, comme Smalltalk, les opérations peuvent seulement être déclarées comme méthodes, puisque le langage ne nous autorise pas à déclarer des procédures ou des fonctions séparées de toute classe. En comparaison, des langages comme C++ et Ada autorisent le développeur à écrire des opérations comme des sous-programmes libres. Ce sont des procédures ou des fonctions qui servent d'opérations non primitives sur un ou plusieurs objets de la même classe ou de classes différentes. Les sous-programmes libres sont typiquement groupés selon les classes sur lesquelles ils sont construits ; Par exemple, nous pourrions écrire la fonction non-membre suivante void copyUntilFound(Queue& from, Queue& to, void* item);

Page 11: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 11/58

Le but de cette opération est de copier et dépiler la file jusqu’à ce qu'un élément donné soit arrivé en tête de la file. Cette opération n'est pas primitive ; elle peut être construite à partir d'opérations de plus bas niveau qui font déjà partie de la classe Queue. C'est une habitude courante en C++ de regrouper tous les sous-programmes libres qui sont liés logiquement et de les déclarer dans une classe n'ayant pas d'état. En C++, ils deviennent alors statiques. Ainsi, nous pouvons dire que toutes les méthodes sont des opérations, mais toutes les opérations ne sont pas des méthodes: certaines peuvent être des sous-programmes libres. En pratique, on déclare la plupart des opérations comme des méthodes, sauf si il existe des raisons impérieuses de faire autrement. Par exemple, lorsqu'une opération particulière affecte deux objets ou plus de classes différentes, et qu'il n'y ait aucun avantage particulier à déclarer cette opération dans une classe plutôt que dans une autre.

Page 12: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 12/58

Diapositive 8

25/03/2001 Cours B4: Programmation et développement orientés objets 8/42

Rôles et responsabilitésLes méthodes et utilitaires de classes associés à un objet forment son protocoleL’état et le comportement de l’objet définissent les différents rôles qu’il peut jouerL’analyse d’un problème commence par l’examen des différents rôles que joue un objetLa conception déterminera les opérations spécifiques constituant les responsabilités de chaque rôle

La majorité des objets intéressants jouent en fait plusieurs rôles différents durant leur existence Par exemple • Un compte bancaire peut être débiteur ou créditeur, et le rôle qu'il joue influe sur la sémantique d'un retrait d'argent. • Pour un financier, une action représente une abstraction ayant une valeur et pouvant être achetée ou vendue. Pour un juriste, cette même action représente un instrument légal offrant certains droits. • Durant une même journée, un individu peut jouer le rôle de mère, médecin, jardinier et critique de film.

Page 13: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 13/58

Diapositive 9

25/03/2001 Cours B4: Programmation et développement orientés objets 9/42

Caractérisation de l’état par une machine

Les objets ont généralement un état dépendant de l’ordre dans lequel sont appelées les opérationsLe comportement de ces objets peut être caractérisé par un automate d’états finisOn distingue aussi les objets actifs des objets passifs

Un objet actif est un objet qui contient sa propre tâche de contrôle, contrairement à un objet passif. Les objets actifs sont généralement autonomes, ce qui signifie qu'ils peuvent présenter un certain comportement sans qu'un autre objet agisse sur eux. Les objets passifs, d'un autre côté, ne peuvent subir un changement d'état que lorsqu'on agit explicitement sur eux. Si un système implique de multiples flots de contrôle, alors il y aura souvent de multiples objets actifs. A l'inverse, les systèmes séquentiels ont généralement un seul objet actif, par exemple un objet fenêtre principale responsable de la gestion d'une boucle d'événements qui achemine les messages. Dans de telles architectures, tous les objets sont passifs et leur comportement est déclenché parles messages du seul objet actif.

Page 14: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 14/58

Diapositive 10

25/03/2001 Cours B4: Programmation et développement orientés objets 10/42

L’identité d’un objetL’identité d’un objet est la caractéristique qui le distingue de tous les autres objetsL’identité d’un objet est différente du nom d’un objetUn objet peut avoir plusieurs noms c’est le partage de structureLe partage de structure est à l’origine de nombreux problèmes en programmation orientée objets

la plupart des langages de programmation utilisent les noms de variables pour distinguer les objets temporaires, mélangeant adressage et identité. L'oubli de la distinction entre le nom d'un objet et l'objet lui-même est à l'origine de beaucoup d'erreurs dans la programmation orientée objets.

Page 15: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 15/58

Diapositive 11

02/04/2001 Cours B4: Programmation et développement orientés objets 11/42

Problème d’identité (1/2)struct Point {

int x;

int y;

Point():x(0),y(0) {}

Point(int xValue, int yValue):x(xValue), y(yValue) {}

};class DisplayItem {

public:DisplayItem();DisplayItem(const Point& location);

virtual ~DisplayItem();

virtual void Draw();virtual void Erase();

virtual void Move(const Point& location);

...

int IsSelected() const;

Point Location() const;int IsUnder(const Point& location) const;

...protected:....

};

DisplayItem item1;

DisplayItem* item2 = newDisplayItem(Point(75,75));DisplayItem* item3 = newDisplayItem(Point(100,100));DisplayItem* item4 = 0;

//Exécution 2item1.Move(item3->location());

item4 = item3;

item4->Move(Point(38,100));

// Execution 3item2 = &item1;item4->Move(item2->Location()):

Point est une structure et non une classe. La règle autorisant cette distinction est simple. Si l'abstraction représente un simple enregistrement d'autres objets, et n'a aucun comportement propre qui s'appliquerait à l'objet dans son ensemble, il faut choisir une structure. Pour l'abstraction Point, nous définissons un point comme représentant une coordonnée (x, y) du plan. Pour plus de facilité, nous offrons un constructeur par défaut, qui crée la valeur (0 , 0), et un autre qui initialise un point avec des coordonnées explicites. L’abstraction DisplayItem représente un élément graphique. Nous avons là une abstraction qui est plus qu'un simple groupement de données. Les clients s'attendent à pouvoir afficher, sélectionner et déplacer des objets graphiques, ainsi qu'à lire leur état de sélection et leur position. Elle est définie par une classe. On declare des instances de cette classe. Comme le transparent suivant le montre, ces déclarations créent quatre noms et trois objets distincts. Plus précisément, elle réserve quatre emplacements en mémoire, dont les noms sont item1, item2, item3 et item4 , Le premier est le nom d'un objet DisplayItem particulier, mais les trois autres désignent des pointeurs sur de tels objets. Seuls item2 et i tem3 pointent sur de vrais objets (parce que leur déclaration inclut l'allocation d'un nouvel objet) ; item4 ne désigne rien. Qui plus est, les objets désignés par item2 et item3 sont anonymes : nous ne pouvons y faire référence que de façon indirecte, en déréférençant leur pointeur. Nous pouvons dire que item2 pointe sur un objet DisplayItem distinct, auquel nous avons accès indirectement par *item2.

Page 16: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 16/58

Si on exécute les instructions 2 Nous constatons que l'objet item et celui désigné par item2 ont maintenant la même position, et que item4 désigne le même objet que item3. Remarquez que nous utilisons la phrase «l'objet désigné par item2» plutôt que «l'objet item2». La première est plus précise. Même si item1 et l'objet désigné par item2 ont le même état, ils représentent des objets différents. Remarquez aussi que nous avons altéré l'état de l'objet pointé par item3 en agissant par l'intermédiaire de son nouveau nom indirect, item4. Cette situation se nomme partage de structure et signifie qu'un objet peut être nommé de plusieurs façons. En d'autres termes, il existe des synonymes pour cet objet. La non prise en compte des effets de bord d'une action sur un objet, par l'intermédiaire d'un synonyme, provoque souvent des déperditions de mémoire, erreurs d'accès en mémoire ou, des changements intempestifs d'état. Par exemple, si nous détruisons l'objet désigné par item3, à l'aide de l'expression delete item3, la valeur du pointeur item4 perdrait toute signification. Cette situation se nomme une référence pendante (dangling reference). Après exécution 3 La première ligne crée un pseudonyme, car item2 désigne alors le même objet qu'item1. La seconde instruction lit l'état d' item1 à travers ce pseudonyme. Par malheur, nous avons provoqué une déperdition de mémoire. L'objet que désignait initialement item2 ne peut plus être nommé, directement ou indirectement, et son identité est donc perdue. Dans des langages comme Smalltalk ou JAVA, de tels objets seront recyclés automatiquement et l'espace qu'ils occupent sera réutilisé. Mais avec des langages comme C++, leur espace mémoire ne peut être recyclé avant la fin du programme qui les a créés. Les problèmes de déperditions de mémoire peuvent être ennuyeux, voire désastreux, surtout pour les programmes dont l'exécution dure longtemps.

Page 17: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 17/58

Diapositive 12

02/04/2001 Cours B4: Programmation et développement orientés objets 12/42

Problème d’identité (2/2)

Item 1

Point = (0,0)

Item 1

Point = (0,0)Point = (75,75)

Point = (75,75)

Point = (100,100)

Point = (100,100)

Item 2 Item 3 Item 4

O

Item 1Point =

(100,100)

Item 1Point =

(100,100)Point = (75,75)

Point = (75,75)

Point = (38,100)

Point = (38,100)

Item 2 Item 3 Item 4

Item 1Point =

(100,100)

Item 1Point =

(100,100)Point = (75,75)

Point = (75,75)

Point = (100,100)

Point = (100,100)

Item 2 Item 3 Item 4

Page 18: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 18/58

Diapositive 13

25/03/2001 Cours B4: Programmation et développement orientés objets 13/42

Copie, Affectation, EgalitéLa copie l’affectation et l’égalité doivent être controléesConstructeur de copie:

X(const& X);

Opérateur d’affectationvirtual X& operator=(const X&);

Opérateurs d’égalitéVirtual int operator==(const X&) const;Int operator!=(const X&) const;

Le partage de structure a lieu quand l'identité d'un objet est dupliquée par affectation d'un second nom. Dans la plupart des applications orientées objets intéressantes, l'utilisation de synonymes ne peut simplement pas être évitée. Par exemple, examinez les deux déclarations de fonctions ci-dessous void highlight (DisplayItem& i); void drag (DisplayItem i) ; L'appel de 1a première fonction, avec item1 comme argument, crée un synonyme: le paramètre formel i est une référence sur l'objet désigné par le paramètre réel, et donc item1. et i désigneront le même objet durant l'exécution de la fonction. Par contre, l'appel à la seconde fonction, avec le même paramètre item1, crée une copie du paramètre réel, et il n'y a pas création de synonyme: i désigne un objet totalement différent d'item1. (même s'il présente initialement le même état). Avec des langages comme C++, où il existe une différence entre la transmission par valeur et par référence, il faut prendre des précautions afin d'éviter d'agir sur une copie d'un objet alors qu'il fallait agir sur l'objet lui-même.. En général, la transmission par référence est préférable pour tous les objets non élémentaires, car sa sémantique est celle d'une copie de référence et non d'état ->Elle est donc bien plus efficace mais certaines situations, une copie effective est l'effet recherché .Avec des langages comme C++, nous pouvons contrôler la sémantique de ces opérations. En C++, Il est possible de créer un constructeur-copieur dans la déclaration d'une classe. En l'absence d'une telle fonction, un constructeur-copieur par défaut est invoqué. La sémantique de ce dernier est celle d'une copie membre à membre. Toutefois, pour les objets dont l'état inclut des pointeurs ou des références sur d'autres objets, une telle copie est souvent dangereuse, car elle crée des synonymes de bas niveau. La règle générale que nous appliquons est donc de ne tolérer

Page 19: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 19/58

l'omission d'un constructeur-copieur que pour les abstractions dont l'état est composé uniquement de valeurs élémentaires. Dans tous les autres cas, nous écrivons un constructeur-copieur explicite. Cette pratique distingue ce que certains nomment la copie profonde et la copie superficielle (deep copy ou shallow copy). De même, l'affectation, ou assignation, est souvent une simple opération de copie et, avec des langages comme C++, sa sémantique peut aussi être contrôlée. Cet opérateur est déclaré virtuel afin qu'une sous-classe puisse le redéfinir. Comme pour le constructeur-copieur, nous pouvons écrire cette fonction afin qu'elle offre une sémantique de copie profonde ou superficielle. L'omission d'une telle déclaration provoque l'invocation de l'opérateur d'affectation par défaut, dont la sémantique est celle d'une copie membre à membre. Bien que cela semble un concept simple, l'égalité peut avoir deux significations différentes. Premièrement, l'égalité peut signifier que deux noms désignent le même objet. Deuxièmement, l'égalité peut signifier que les objets sont différents mais que leurs états sont identiques. Par exemple, dans le transparent précédent (en bas), la première sorte d’égalité est vraie entre iteml et item2 et la deuxième sorte d'égalité est vraie entre item2 et item3. Il n'existe pas d'opérateur d'égalité par défaut en C++. Nous devons donc définir notre propre sémantique en introduisant des opérateurs explicites pour l'égalité ou l'inégalité d'objets. Nos règles sont de déclarer l'opérateur d'égalité comme virtuel (car les sous-classes peuvent ainsi le surcharger) et l'opérateur d'inégalité comme non virtuel (pour qu'il offre toujours la sémantique inverse de l'égalité; les sous-classes ne doivent pas redéfinir ce comportement). Nous pourrions tout aussi bien définir la signification des opérateurs de comparaison entre objets comme l'infériorité ou la supériorité.

Page 20: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 20/58

Diapositive 14

25/03/2001 Cours B4: Programmation et développement orientés objets 14/42

Durée de vie d’un objetElle s’étend de l’allocation d’un espace d’un objet jusqu’au moment il est récupéréUn objet peut être:

Déclaré -> crée dans l’espace de donnéesParamètre -> crée sur la pileAlloué -> crée sur le tas

Opérateurs new et delete

La création peut être explicite ou implicite

Un objet est soit déclaré, soit alloué (sur le tas) En C++, dans les deux cas, quand un objet est créé, son constructeur est automatiquement invoqué. Le rôle de celui-ci est d'allouer de l'espace pour l'objet et d'initialiser son état. Les objets sont souvent créés de façon implicite. Ainsi, en C++, la transmission par valeur d'un objet crée, sur la pile, une copie du paramètre réel. De plus, la création est transitive: créer un objet agrégé provoque aussi la création de tous les objets qu'il contient. La surcharge des opérateurs de copie et d'affectation permet, en C++, de contrôler la création et la destruction de ces composants. Il est aussi possible de redéfinir la sémantique de l'opérateur new (qui alloue des instances dans le tas) afin que chaque classe dispose de sa propre politique de gestion de la mémoire. Destruction: Avec des langages comme JAVA, les objets sont détruits automatiquement, quand toutes leurs références ont été perdues, par le ramasse-miettes. Avec des langages sans ramasse-miettes, comme C++, un objet existe aussi longtemps qu'il occupe de l'espace, même si toutes ses références sont perdues. Un objet créé dans la pile du programme est détruit quand 1e contrôle sort du bloc dans lequel l'objet a été déclaré. Les objets créés sur le tas par l'opérateur new doivent être détruits explicitement par delete. L'oubli de cette règle provoque des déperditions de mémoire. La double libération d'un objet (souvent à cause d'un synonyme) est aussi mauvaise et peut se manifester par une corruption de 1a mémoire ou un arrêt brutal du programme. En C++, quand un objet est détruit, explicitement ou non, son destructeur est invoqué. Son rôle est de libérer l'espace occupé par l'objet et ses composants, et de faire divers nettoyages (comme refermer les fichiers ouverts et libérer des ressources). Les destructeurs ne libèrent pas automatiquement l'espace alloué par new

Page 21: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 21/58

Diapositive 15

25/03/2001 Cours B4: Programmation et développement orientés objets 15/42

Relations entre objetsDeux sortes de relations sont utiles:

Les relations de liens (ou d’utilisation)Les relations d’agrégation (ou parent-enfant)

Un objet par lui-même est totalement inintéressant. Les objets contribuent au comportement d'un système en collaborant les uns avec les autres. Par exemple seuls les efforts conjugués de tous les objets composant un avion lui permettent de voler. La relation entre chaque couple d'objets renferme l'hypothèse que chacun connaît l'autre, y compris les opérations qui peuvent être effectuées et le comportement qui en résulte.

Page 22: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 22/58

Diapositive 16

25/03/2001 Cours B4: Programmation et développement orientés objets 16/42

Relations d’utilisationC’est une connexion physique ou conceptuelle entre objetsDans ces relations un objet peut jouer les rôles :

D’acteurUn objet qui peut agir sur d’autres objets mais sur lequel les autres objets ne peuvent agir

De serveurUn objet qui n’agit jamais sur d’autres objets; mais les autres objets agissent sur lui

D’agentUn objet qui peut agir sur d’autres objets et sur lequel les autres objets peuvent agir

Page 23: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 23/58

Diapositive 17

25/03/2001 Cours B4: Programmation et développement orientés objets 17/42

Exemple de liens entre objets

aController aView

B: DisplayItem

A: DisplayItemMove()

isUnder()

La figure illustre les relations d'utilisation entre plusieurs objets. Dans cette figure, une ligne entre deux symboles d'objets représente l'existence d'un lien et signifie que des messages peuvent passer le long de ce chemin. Les messages sont représentés par une flèche orientée qui indique le sens de l'échange, avec un libellé associé au message lui même. Par exemple, nous pouvons constater que l'objet aController a des liens vers deux instances de DisplayItem (les objets a et b). Bien que tous deux aient probablement des liens sur la vue dans laquelle ils sont affichés, nous n’en avons montré qu'un seul, de a vers aView. Les messages ne peuvent être émis que le long de ces liens. Le passage des messages entre deux objets est généralement unidirectionnel, bien qu'une communication bidirectionnelle soit aussi possible. Dans notre exemple, l'objet aController indique uniquement des opérations sur les deux objets affichés (pour en déplacer un et demander la position de l'autre), mais ces objets n'agissent pas sur le contrôleur. Cette séparation des problèmes est relativement courante dans les systèmes orientés objets bien structurés Vous noterez aussi que, bien que la transmission d'un message soit initiée parle client (ici acontroller) et soit dirigée vers le fournisseur (a ou b), des données peuvent être transmises dans les deux directions sur un même lien. Par exemple, lorsque aController invoque l'opération Move sur a, des données transitent du client au fournisseur. Mais lors de l'appel de isUnder sur b, le résultat va du fournisseur au client. AController représente un acteur, aView est un serveur et a est un agent qui exécute les requêtes du contrôleur afin d'afficher l'objet dans une vue.

Page 24: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 24/58

Diapositive 18

25/03/2001 Cours B4: Programmation et développement orientés objets 18/42

Visibilité et synchronisationVisibilité

L'objet fournisseur est global pour le client.L'objet fournisseur est un paramètre d'une opération du client.L'objet fournisseur est une partie de l'objet client.L'objet fournisseur est un objet déclarélocalement dans l'une des opérations du client.

SynchronisationSéquentielleProtégéeSynchrone

La visibilité. Soient deux objets A et B, avec un lien entre eux. Afin que A puisse envoyer un message à B, celui-ci doit être visible, d'une certaine manière, depuis A. Lors de notre analyse d'un problème, on peut ignorer ces détails de visibilité. Mais, dès que nous commençons à envisager une mise en oeuvre concrète, nous devons prendre en compte la visibilité le long des liens, car nos décisions dicteront alors la portée et les accès aux objets de chaque côté du lien. Il n’existe que 4 façons pour qu’un objet en voit un autre et le choix de la solution est une décision tactique de conception. La synchronisation: Quand un objet passe un message à un autre le long d'un lien, les deux objets sont dits synchronisés. Pour les objets d'une application complètement séquentielle, cette synchronisation est habituellement accomplie par des appels de méthodes. Les objets impliqués dans des tâches de contrôles multiples requièrent une synchronisation plus sophistiquée, afin de traiter les problèmes d'exclusion mutuelle qui peuvent se produire dans les systèmes concurrents. Les objets actifs contiennent leur propre flot de contrôle. Nous attendons donc que leur sémantique soit préservée en présence d'autres objets actifs. Cependant, lorsqu'un objet actif a des liens avec un objet passif, nous devons choisir entre trois approches de synchronisation Séquentielle la sémantique de l'objet passif est préservée en présence d'un seul objet actif à un moment donné Protégée la sémantique de l'objet passif est assurée en présence de multiples flots de contrôle, mais les clients doivent coopérer pour une exclusion mutuelle

Page 25: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 25/58

Synchrone la sémantique de l'objet passif est préservée en présence de multiples flots de contrôle, et le fournisseur garantit l'exclusion mutuelle

Page 26: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 26/58

Diapositive 19

25/03/2001 Cours B4: Programmation et développement orientés objets 19/42

Relation d’agrégation d’objetsElle dénote une relation ensemble / composant (ou parent / enfant)Elle offre la possibilité de naviguer de l’ensemble vers ses constituantsL’agrégation peut être associé ou non à un inclusion physique

Alors que les liens dénotent une relation client/fournisseur, la contenance (ou agrégation) correspond à une hiérarchie ensemble/ composant, avec la possibilité de naviguer de l'ensemble (aussi appelé l'agrégat) vers ses constituants (ou attributs). L'agrégation est, en cela, un type particulier d'association. L'agrégation peut ou non, être associée à une inclusion physique. Par exemple, un avion est constitué des ailes, moteurs, train d'atterrissage, etc. Nous avons là une inclusion physique. D'un autre côté, la relation entre un actionnaire et ses investissements est aussi une agrégation, mais sans inclusion physique. L'actionnaire possède de façon exclusive des actions mais ces dernières ne font pas physiquement partie du premier. Cette relation ensemble/ composant est plus conceptuelle et donc moins directe que l'agrégation des éléments qui constituent un avion. Il existe des compromis entre les relations d'utilisation et de contenance. La seconde est parfois meilleure que la première parce qu'elle encapsule les composants, qui sont cachés dans l'ensemble. Les liens sont parfois meilleurs car ils autorisent un couplage faible entre les objets. Un choix intelligent nécessite une juste évaluation de ces deux facteurs.

Page 27: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 27/58

Diapositive 20

25/03/2001 Cours B4: Programmation et développement orientés objets 20/42

Nature d’une classeUne classe est un ensemble d’objets qui partagent une structure commune et un comportement communElle offre une interface

PubliquePrivéeProtégée

Elle contient une mise en oeuvre

Les concepts de classe et d'objet sont étroitement liés mais il y a des différences importantes entre ces deux termes. Un objet est une abstraction concrète qui existe dans le temps et l'espace, une classe représente seulement une abstraction, l'«essence» d'un objet. Ainsi, nous pouvons parler de la classe mammifère, qui représente les caractéristiques communes à tous les mammifères. Pour identifier un mammifère particulier de cette classe, nous devons parler de «ce mammifère-ci». Un objet est simplement une instance d'une classe. Qu'est-ce qui n'est pas une classe? Un objet n’est pas une classe. Les objets qui ne partagent pas une structure et un comportement communs ne peuvent être regroupés dans une classe parce que, par définition, ils ne sont pas reliés, excepté par leur nature générale d'objets. Il est important de remarquer que la classe - comme définie dans la majorité des langages de programmation - est un véhicule nécessaire, mais pas suffisant, pour la décomposition. Les abstractions sont parfois si complexes qu'il n'est pas possible de les exprimer en termes d'une classe unique. Par exemple: à un niveau d'abstraction suffisamment élevé, une interface graphique, une base de données et un système de gestion de stocks sont tous des objets particuliers. Aucun ne peut être représenté par une classe unique. Il est préférable de regrouper ces abstractions dans un ensemble de classes dont les instances collaborent afin d'offrir le comportement et la structure voulus. Interface et mise en œuvre

Page 28: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 28/58

les diverses fonctions d'un gros problème sont décomposées en plus petits problèmes en les sous-traitant à différentes classes Alors qu'un objet individuel est une entité concrète qui joue un certain rôle dans le système général, la classe formalise la structure et le comportement communs des objets reliés. Ainsi, une classe est une sorte de contrat entre une abstraction et tous ses clients. Cette idée de la programmation par contrats nous amène à faire la distinction entre la vue externe et la vue interne d'une classe. L'interface d'une classe fournit sa vue extérieure et, par conséquent, met l'accent sur l'abstraction alors qu'elle cache sa structure et les secrets de son comportement. Cette interface consiste avant tout en déclarations de toutes les opérations applicables aux instances de cette classe. Elle peut aussi inclure la déclaration d'autres classes, constantes, variables et exceptions nécessaires pour compléter l'abstraction. Par comparaison, la mise en oeuvre d'une classe est sa vision interne, qui contient les secrets de son comportement. Elle consiste d'abord en la mise en oeuvre de toutes les opérations définies dans l'interface de la classe. Nous pouvons encore diviser l'interface d'une classe en trois parties Public une déclaration accessible à tous les clients Protégée une déclaration qui n'est accessible qu'à la classe, à ses amies et à ses sous-classes Privée une déclaration qui n'est accessible qu'à la classe et à ses amies

Page 29: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 29/58

Diapositive 21

25/03/2001 Cours B4: Programmation et développement orientés objets 21/42

Relations entre classeLa plupart des langages OO supportent les relations:

AssociationHéritageAgrégationUtilisation

Certains langages OO supportent les relations:

InstanciationMéta-classe

Il existe en tout trois types fondamentaux de relations de classes. Le premier d'entre eux est la généralisation/ spécialisation, qui désigne une relation «est un». Par exemple, une rose est une sorte de fleur, ce qui signifie qu'une rose est une sous-classe spécialisée d'une classe plus générale de fleur. Le second est l'ensemble/composant, qui dénote une relation «partie de». Ainsi un pétale n'est pas une sorte de fleur, c'est une partie d'une fleur. Le troisième est l'association, qui désigne une dépendance sémantique parmi des classes qui ne sont pas reliées autrement, comme les coccinelles et les fleurs. L'héritage est probablement la plus puissante de ces relations et existe pour exprimer la généralisation/spécialisation. L'héritage est toutefois insuffisant pour exprimer toute la richesse des relations qui peuvent exister parmi les abstractions fondamentales du domaine d'un problème donné. Nous avons aussi besoin de l'agrégation, qui offre les liens ensemble/composant entre instances de classes. De plus, nous avons besoin des relations d'utilisation, qui établissent les liens entre les instances des classes. les associations sont les plus générales mais aussi les plus faibles du point de vue sémantique. Les relations de méta-classe sont tout à fait distinctes et ne sont supportées que par des langages comme Smalltalk. En résumé, une méta-classe est la classe d'une classe, ce qui nous autorise à traiter les classes comme des objets.

Page 30: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 30/58

Diapositive 22

25/03/2001 Cours B4: Programmation et développement orientés objets 22/42

AssociationElle dénote la dépendance sémantique en deux classesC’est un lien bi-directionnelElle a une cardinalité

1 pour 11 pour nn pour n

Elle peut être représentée en C++ par des pointeurs inclus

Par exemple: nous pouvons trouer une association simple entre deux classes: la classe Produit dénote les produits vendus dans une transaction, et la classe Vente désigne la vente durant laquelle plusieurs produits ont changé de mains. Cette association suggère, indirectement, une relation bidirectionnelle : pour une instance de Produit, nous devons pouvoir trouver l'objet correspondant à sa vente et, pour une instance de sale, nous devons pouvoir trouver tous les objets vendus dans la transaction. Une association un pour un est très étroite. Par exemple, dans la vente par correspondance, nous pourrions trouver une relation un pour un entre la classe Vente et la classe TransactionCarteDeCredit :il existe une transaction par carte de crédit pour chaque vente, et une vente pour chaque transaction par carte de crédit. Les relations n pour n sont aussi courantes. Ainsi, chaque instance de la classe Client peut provoquer une transaction avec la classe Vendeur, et chaque vendeur peut interagir avec plusieurs clients

Page 31: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 31/58

Diapositive 23

25/03/2001 Cours B4: Programmation et développement orientés objets 23/42

Exemple d’associationclass Produit;

class Vente;

class Produit {

public:

....

protected:

Vente * _laVente;

};

class Vente {

public:

....

protected:

Produit** _produitVendu;

};

Page 32: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 32/58

Diapositive 24

25/03/2001 Cours B4: Programmation et développement orientés objets 24/42

HéritageHéritage simple

Relation entre deux classes dont l’une (la sous classe) partage la structure et le comportement de l’autre (la super classe)

La hiérarchie définie la relation « est un » entre classesDans une structure d’héritage, il y a des classes concrètes et des classes abstraitesDans un arbre hiérarchique, la classe la plus générale est appelée classe de baseConflit entre encapsulation et héritage

Parties publiques, protégées, privées

Le Test « est un est vraiment le test de vérité pour l’héritage Une sous-classe augmente ou restreint souvent la structure et le comportement de ses surclasses. On parle d'héritage pour extension lorsqu'une sous-classe augmente ses super-classes. Par exemple la classe Figure3D peut augmenter les capacité de la classe Figure2d en ajoutant des comportements et des attributs spécifiques à la 3d. Par opposition, on parle d'héritage pour restriction lorsqu'une sous-classe limite le comportement de ses super-classes. Par exemple, la sous-classe FigureNonSelectable peut restreindre le comportement de sa super-classe, Figure, en interdisant que des clients ne sélectionnent ses instances. Dans la pratique, il n'est pas toujours très clair de savoir si une classe augmente ou restreint le comportement de ses super-classes. Elle fait bien souvent les deux. Certaines classes ont des instances, et certaines n'en ont pas. Par exemple, nous nous attendons à avoir des instances de chacune des classes les plus spécialisées (aussi appelées classes terminales, ou classesconcrètes) telles que Rectangle, Cercle….Cependant, il est peu probable que nous ayons des instances des classes intermédiaires plus générales, telles que FigureGéométrique. Les classes sans instances sont dites classes abstraites. Elles sont écrites dans l'attente que leurs sous-classes enrichissent leur structure et leur comportement, souvent en complétant leurs méthodes (en général) incomplètes. C++ autorise le développeur à préciser qu'une méthode d'une classe abstraite ne peut pas être invoquée directement, en initialisant sa déclaration à zéro. Une telle méthode est appelée fonction virtuelle pure, et le langage interdit la création d'instances dont la classe exporte de telles fonctions. En java les interfaces réalisent cette fonction. La classe la plus générale dans une structure de classes est appelée 1a classe de base. La plupart des applications ont beaucoup de classes de base, qui représentent les catégories d'abstractions les plus générales du domaine concerné. C++, les architectures orientées objets bien

Page 33: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 33/58

structurées contiennent une forêt d'arbres d'héritage, plutôt qu'un seul arbre aux racines profondes. Toutefois, certains langages imposent une classe de base générale. En Smalltalk, elle se nomme Object. Une classe donnée a en général deux sortes de clients • Les instances • Les sous-classes II est utile de définir des interfaces différentes pour ces deux sortes de clients. Nous voulons ne rendre accessible aux clients que les comportements visibles (préservation de l’encapsulation), alors que les fonctions support et la représentation interne ne doivent être accessibles qu'aux sous-classes (ouverture de l’encapsulation). Ceci est précisément la motivation des parties publique, protégée et privée d'une classe en C++ : le concepteur peut choisir quels membres sont visibles des instances, des sous-classes, et des deux. Il y a un réel conflit entre héritage et encapsulation. Dans une très large mesure, l'héritage expose certains des secrets d'une classe héritée. Cela signifie en pratique que, pour comprendre la signification d'une classe particulière, on doit souvent étudier toutes ses super-classes, y compris parfois leur vue interne. L'héritage signifie que les sous-classes héritent de la structure de leur super-classe. Les sous-classes héritent aussi du comportement de leurs super-classes. La plupart des langages de programmation orientés objets permettent aux méthodes d'une super-classe d'être redéfinies dans une sous-classe et autorisent l'ajout de nouvelles méthodes. En Smalltalk, par exemple, chaque méthode d'une super-classe peut être redéfinie dans une sous-classe. En C++, le développeur a un peu plus de contrôle. Les fonctions membres qui sont déclarées virtuelles peuvent être redéfinies dans une sous-classe; les membres déclarés autrement (choix par défaut) ne peuvent pas être redéfinis.

Page 34: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 34/58

Diapositive 25

25/03/2001 Cours B4: Programmation et développement orientés objets 25/42

Exemple d’héritageFigure

PolygoneEllipse

Rectangle Hexagone OctogoneCercle

La classe de base figure peut définir la structure et le comportement de toutes figures géométriques. Par exemple: définition de la couleur du trait de la couleur de remplissage,… définition des comportements généraux tels fixer et lire les couleurs, sélectionner la figure, calculer la surface… Les classes plus spécialisées étendent se comportements. Par exemple la classe polygone peut définir en plus le nombre de sommets. La classe Figure n’aura certainement pas d’instance classe abstraite car par exemple on se sait pas calculer la surface d’une figure quelconque.

Page 35: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 35/58

Diapositive 26

25/03/2001 Cours B4: Programmation et développement orientés objets 26/42

Polymorphisme simpleUn nom peut désigner des objets de nombreuses classes différentes reliées par une super classe commune.Sans polymorphisme, le code écrit est constitué de grandes parties d’instructions de choix multiplesLe polymorphisme donne toutes son utilité à l’héritageLe polymorphisme et la résolution dynamique vont de pair

Figure* fig[10]; Fig[0]= new Rectangle(…); Fig[1]= new Cercle(…); …. For (int i=0; i < 10; i++) { fig[i].Surface(); } En pascal on pourrait utiliser des enregistrements variable pour désigner les figures géométriques: Const: Rectangle = 1; Cercle = 2; Triangle = 3; … Procedure Surface (LaFigure: Figure); Begin case LaFigure.EstDuType of Rectangle: SurfaceRectangle(LaFigure); Cercle: SurfaceCercle(LaFigure); Triangle: SurfaceTriangle(laFigure); end

Page 36: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 36/58

End; Pour ajouter un autre type de donnée, nous devrions modifier la variante de l'enregistrement et enrichir chaque sélection multiple qui utilise ces enregistrements. C'est une grande source d'erreurs qui, de plus, rajoute de l'instabilité à la conception. Avec le polymorphisme, les grands choix multiples ne sont pas nécessaires, parce que chaque objet connaît implicitement son propre type. L'héritage sans polymorphisme est possible, mais il n'est certainement pas très utile. C'est le cas en Ada, dans lequel on peut déclarer des types dérivés mais, comme ce langage est monomorphique, l'opération qui sera appelée est toujours connue à la compilation. Le polymorphisme et la résolution dynamique vont de pair. En présence de polymorphisme le lien entre une méthode et un nom n'est pas déterminé avant l'exécution. En C++, le développeur peut contrôler si une fonction membre utilise une résolution statique ou dynamique en utilisant la directive virtual. Si une méthode est déclarée virtuelle sa résolution sera dynamique sinon sa résolution sera statique et faite pendant la compilation.

Page 37: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 37/58

Diapositive 27

25/03/2001 Cours B4: Programmation et développement orientés objets 27/42

Héritage et TypageLa plupart des langages OO permettent à un objet d’une classe d’appeler les méthode de sa super-classeL’affectation d’un objet de type X à un objet de type Y est possible si Y est une super-classe de XUne conversion de type est nécessaire pour effectuer l’opération d’affection inverseC++ permet de contrôler le sous-typage obtenu par héritage

l’héritage privé ne crée pas un sous-type de la super-classe.

En C++, le développeur a un grand contrôle sur les implications de l’héritage. Spécifiquement, si nous affirmons que la super-classe d'une sous-classe donnée est publique alors nous signifions que la sous-classe est aussi un sous-type de la super-classe, puisque les deux partagent la même interface (et par conséquent, la même structure et le même comportement). A l'opposé, dans la déclaration d'une classe, on peut indiquer qu'une super-classe est privée, ce qui signifie que la structure et le comportement de la super-classe sont partagés mais que la sous-classe n'est pas un sous-type de la super-classe. Cela signifie que, pour les super-classes privées, les membres publics et protégés de la super-classe deviennent des membres privés de la sous-classe, donc invisibles aux classes plus spécialisées. De plus, aucune relation de sous-type n'existe entre la sous-classe et ses sous-classes privées, car elles ne présentent plus la même interface aux autres clients. Les règles du C++ interdisent de rendre un membre d'une sous-classe plus visible qu'il ne l'est dans sa super-classe.

Page 38: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 38/58

Diapositive 28

25/03/2001 Cours B4: Programmation et développement orientés objets 28/42

Héritage multipleUne classe partage la structure et de comportement de plusieurs super-classesA utiliser avec précautionProblèmes a traiter:

Conflits de nomsHéritage répété

La nécessité de l'héritage multiple dans les langages de programmation orientés objets est encore un sujet de grand débat. l'héritage multiple est comme un parachute: on n'en a pas toujours besoin, mais quand c'est le cas, on est vraiment content de l'avoir sous la main. Le test de vérité de l'héritage multiple: Si nous rencontrons une série de classes dont les classes terminales peuvent être groupées en ensembles offrant des comportements orthogonaux (comme les formes géométriques et leur représentation sur un écran), et si ces ensembles se chevauchent, cela signifie que, avec l'héritage simple, il est impossible de définir des classes intermédiaires qui représenteraient correctement ces comportements sans violenter les classes terminales, certaines héritant de comportements dont elles n'ont pas besoin. Cette situation est résolue par l'héritage multiple, qui permet de ne mélanger les comportements que lorsque c'est utile. Concevoir une structure de classes convenable impliquant l'héritage, surtout l'héritage multiple, est une tâche difficile Les conflits de noms surviennent quand deux super-classes différentes, ou plus, utilisent le même nom pour un certain élément de leur interface, tel que des variables d'instance et des méthodes. Que signifie hériter de deux champs ayant le même nom ? Il s'agit d'un problème clé de l'héritage multiple: les conflits peuvent introduire des ambiguïtés dans le comportement de la sous-classe. Il existe trois approches pour résoudre les collisions. D'abord, la sémantique du langage pourrait voir un conflit de noms comme illégale, et rejeter la compilation de la classe. C'est l'approche prise par des langages comme Smalltalk et Eiffel. Ensuite, la sémantique du langage pourrait voir le même nom, introduit par des classes différentes, comme désignant le même champ, ce qui est l'approche prise par CLOS.

Page 39: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 39/58

Enfin, la sémantique du langage pourrait permettre la collision mais demander que toutes les références au nom qualifient pleinement la source de sa déclaration. C'est l'approche prise par C++. Le second problème est l'héritage répété : quand une classe est une ancêtre d'une autre de plus d'une façon. Cette situation est appelée héritage répété et doit être traitée proprement II y a trois approches pour traiter ce problème. Premièrement, nous pouvons le considérer comme illégal. C'est l'approche prise par Smalltalk et Eiffel. Deuxièmement, nous pouvons permettre la duplication de super-classes, mais demander l'utilisation de noms pleinement qualifiés pour désigner les membres d'une copie spécifique. C'est l'une des approches prises par le C++. Troisièmement, nous pouvons traiter les références multiples à la même classe comme désignant la même classe. C'est l'approche prise en C++ quand la super-classe répétée est virtuelle. Une classe virtuelle existe quand une sous-classe désigne une autre classe comme sa super-classe et la marque comme virtuelle, pour indiquer que c'est une classe partagée.

Page 40: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 40/58

Diapositive 29

25/03/2001 Cours B4: Programmation et développement orientés objets 29/42

Exemple d’héritage multipleFigureGeo Forme

FormeVide FormePleineFigTriangleFigCercleFigRectangle

Rectangle RectanglePlein Cercle CerclePlein TrianglePleinTriangle

Page 41: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 41/58

Diapositive 30

25/03/2001 Cours B4: Programmation et développement orientés objets 30/42

Relation d’agrégationL’agrégation suggère l’inclusion d’une classe dans une autre.La relation d’agrégation entre deux classes n’est pas symétrique:

Elle implique que l’une des deux classes joue le rôle de conteneur;

Deux variantes:La compositionL’agrégation simple

L'agrégation oriente la relation ensemble /composant. Ainsi, l'objet Radiateur est un élément de l'objet RegulateurDeTemperature, et non l'inverse. La composition représente une inclusion de valeur, c'est-à-dire que l'objet Radiateur n'existe pas sans l'instance de RegulateurDeTemperature qui le contient. Les durées de vie de ces deux objets sont intimement liées: lorsque nous créons une instance de RegulateurDeTemperature, nous créons une instance de la classe Radiateur. Lorsque nous détruisons l'objet RegulateurDeTemperature , nous détruisons l'objet Radiateur correspondant. Il existe aussi une agrégation moins directe, dite inclusion de référence. Dans ce cas, la classe RegulateurDeTemperature désigne toujours l'ensemble, et une instance de Radiateur en fait toujours partie, même si l'accès à cette dernière est indirect. Les durées de vie des deux objets ne sont plus aussi liées qu'avant: nous pouvons créer et détruire indépendamment des instances de chaque classe. L'inclusion par valeur ne peut être cyclique (c'est-à-dire que deux objets ne peuvent être physiquement inclus l'un dans l'autre), alors que l'inclusion par référence le peut (chaque objet peut contenir un pointeur sur l'autre)". Le test de vérité de l'agrégation est le suivant: si, et seulement si, il existe une relation ensemble/ composant entre deux objets, nous devons avoir une relation d'agrégation entre leurs classes respectives. L’héritage multiple et l’agrégation sont souvent confondus: ils faut appliquer les test de vérité.

Page 42: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 42/58

Diapositive 31

25/03/2001 Cours B4: Programmation et développement orientés objets 31/42

Exemples d’agrégationCompositionclass RegulateurDeTemperature {

public:

RegulateurDeTemperature(

Emplacement);

~RegulateurDeTemperature;

...

private:

Radiateur r;

};

Agrégation simpleclass RegulateurDeTemperature {

public:

RegulateurDeTemperature(

Emplacement);

~RegulateurDeTemperature;

...

private:

Radiateur* r;

};

Page 43: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 43/58

Diapositive 32

25/03/2001 Cours B4: Programmation et développement orientés objets 32/42

Relation d’utilisationDécoule de l’utilisation d’une classe dans les traitements d’une fonction d’une autre classeC’est une évolution de l’association qui représente une relation client / fournisseur

Alors qu'une association indique un lie sémantique bidirectionnel, une relation d'utilisation est une des évolutions possible d'une association, dans laquelle nous précisons l'abstraction cliente et l'abstraction fournisseur de certains services. Une classe peut en utiliser une autre de différentes façons: utilisation dans la signature d’un des membres de sont interface utilisation d’un objet local de la classe fournisseur dans un traitement. Ces utilisations ne sont pas l’assertion d'une relation ensemble/composant Les relations d'utilisation strictes sont parfois trop contraignantes, car elles n'autorisent au client que l'exploitation de l'interface publique du fournisseur. Parfois, pour des raisons tactiques, nous devons briser l'encapsulation des abstractions, ce qui est le but du concept d'amis du C++.

Page 44: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 44/58

Diapositive 33

25/03/2001 Cours B4: Programmation et développement orientés objets 33/42

Relation d’instanciationUtilise le concept de généricité

Possibilité de créer des classes qui traitent plusieurs types différents d’objets

L’instanciation permet de fixer le type d’une classe génériqueEntraîne la réalisation de classes paramétrées

Construites par des macrosLe langage fournit explicitement le moyen de créer les classes paramétrées

Page 45: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 45/58

Diapositive 34

25/03/2001 Cours B4: Programmation et développement orientés objets 34/42

Exemple de classe paramétréetemplate<class Item> class Queue {

public:

Queue();

Queue (const Queue<Item>&);

virtual ~Queue();

virtual Queue<Item>& operator=(constQueue<Item>&);

virtual int operator==(const Queue<Item>&) const;

int operator!=(const Queue<Item>&) const;

virtual voici clear();

virtual void append (const Item&);

virtual void pop();

virtual void remove(int at);

virtual int length() const;

virtual int isEmpty() const;

virtual const Item& front() const;

virtual int location(const void*);

protected:

};

UtilisationQueue<int> intQueue;

Queue<Figure *> figQueue;

Notre dernière déclaration de la classe Queue n'était pas satisfaisante car elle n'assurait pas la sécurité du typage.Nous pouvons grandement l'améliorer avec des langages qui autorisent la généricité, comme C++. Notez que, dans cette déclaration, nous n'insérons ni ne retirons plus d'objets par l'intermédiaire de void* (qui empêche le contrôle du typage). Nous le faisons parle biais de la classe Item, qui est un argument du gabarit. Une classe paramétrée ne peut avoir d'instance tant que nous ne l'avons pas instanciée elle-même. Nous pouvons ainsi déclarer deux files d'objets, l'une d'entiers et l'autre d'objets affichables

Les objets intQueue et figQueue sont des instances de classes distinctes, qui ne sont même pas unies par une super-classe commune, bien qu'elles dérivent toutes deux de la même classe paramétrée. Ces instanciations permettent le contrôle des types. Les règles de typage de C++ rejetteront toute instruction qui insérerait ou retirerait autre chose que des entiers de la file intQueue, ou tout autre chose que des instances de Figure (ou d'une sous-classe) de la file FigQueue. Il existe plusieurs façons de construire des classes paramétrée comme QueueNous pouvons d'abord utiliser des macros. C'est le style que l'on utilisait dans les premières versions de C++ mais, comme Stroustrup le fait observer, «cette approche ne fonctionne pas bien, excepté sur une petite échelle » parce que la gestion de telles macros est mal commode et sort de la sémantique du langage. De plus, chaque instanciation résulte en une nouvelle copie du code. Nous pouvons fournir un mécanisme pour paramétrer les classes, comme dans notre exemple. Une classe générique (parfois appelée classe paramétrée) est une classe qui sert de modèle pour d'autres classes -un modèle qui peut être paramétré par d'autres classes, objets et/ou opérations. Une classe

Page 46: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 46/58

paramétrée doit être instanciée (c'est-à-dire que ses paramètres doivent être définis) avant que des objets ne puissent être créés. C++ et Eiffel supportent tous deux les mécanismes des classes génériques.

Page 47: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 47/58

Diapositive 35

25/03/2001 Cours B4: Programmation et développement orientés objets 35/42

Interactions classes / objetsRelations entre classes et objets

Chaque objet est l’instance d’une classe; chaque classe à 0 ou plusieurs instancesLes classes sont statiques; les objets sont créés et détruits durant la vie de l’application

Rôle des classes et des objets dans la conception

Identifier les classes et les objets qui constituent le vocabulaireInventer les structures au moyen desquels les ensembles d’objets travaillent et coopèrent

Pour presque toutes les applications, les classes sont statiques ; par conséquent, leur existence, leur sémantique et leurs relations sont fixées préalablement à l'exécution d'un programme. De même, la classe de la plupart des objets est statique, ce qui signifie que, dès qu'un objet est créé, sa classe est fixée. Pendant l'analyse et les premières étapes de la conception, le développeur a deux tâches principales • Identifier les classes et objets qui constituent le vocabulaire du domaine du problème. • Inventer les structures au moyen desquelles des ensembles d'objets travaillent ensemble pour offrir les comportements qui satisfont aux exigences du problème. Nous appelons collectivement de telles classes et objets les abstractions fondamentales du problème, et nous appelons ces structures coopérantes les mécanismes de mise en oeuvre. Au cours de ces phases de développement, l'attention du développeur doit se porter sur la vue extérieure des abstractions clés et de leurs mécanismes. Cette vue représente l’ossature logique du système et, par conséquent, englobe ses structures de classes et d'objets. Dans des étapes plus avancées de la conception, puis de la mise en oeuvre, la tâche du développeur change: l'intérêt se porte sur la vue interne de ces abstractions clés et mécanismes, y compris leur représentation physique. Nous pouvons exprimer ces décisions de conception comme faisant partie de l'architecture des modules et des processus du système.

Page 48: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 48/58

Diapositive 36

25/03/2001 Cours B4: Programmation et développement orientés objets 36/42

Mesure de la qualité d’une abstraction

Il existe 5 métriques:Le couplageLa cohésionL’adéquationLa complétudeLa primitivité

un système doit être construit au moyen d'un ensemble minimum de parties immuables; ces parties doivent être aussi générales que possible; Pour le développement orienté objets, ces parties sont les classes et les objets qui constituent les abstractions clés du système, et l'ossature est procurée par ses mécanismes. La conception des classes et des objets est un processus incrémental et itératif. Franchement, à part pour les abstractions les plus triviales, il est difficile de définir correctement une classe du premier coup. Comment peut-on savoir si une classe ou un objet donné est bien conçu ? il existe cinq métriques significatives • Le couplage, • la cohésion, • l'adéquation, • la complétude, • la primitivité. le couplage est «la mesure de la rigidité de l'association établie par une connexion entre deux modules. Un couplage fort complique un système puisqu'un module est plus difficile à comprendre, à changer ou à corriger s'il est fortement imbriqué avec d'autres. La complexité peut être réduite en concevant des systèmes avec le couplage le plus faible possible entre modules. Le couplage des modules s'applique aussi à l'analyse et la conception orientée objets, mais le couplage des classes et d'objets est tout aussi important. Cependant, il existe des tiraillements entre les concepts de couplage et d'héritage. D'une part il est souhaitable d'avoir des classes faiblement couplées ; d'autre part l'héritage - qui couple étroitement des super-classes et leurs sous-classes -nous aide à exploiter ce que des abstractions ont en commun.

Page 49: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 49/58

La cohérence mesure simplement le degré de connectivité entre les éléments d'un même module (et, pour la conception orientée objets, entre les éléments d'une classe ou objet). La forme la moins désirable de cohérence est celle de coïncidence, dans laquelle des abstractions sans aucun lien sont jetées dans la même classe ou le même module. Imaginez par exemple une classe renfermant les abstractions de chiens et d'astronefs, dont les comportements n'ont pourtant aucun rapport. La forme la plus souhaitable de cohérence est la cohérence fonctionnelle, dans laquelle les éléments d'une classe ou d'un module coopèrent afin de fournir un comportement bien délimité. Donc, la classe Chien est fonctionnellement cohérente si sa sémantique englobe le comportement d'un chien, le chien entier, et rien d'autre que le chien. Adéquat veut dire que la classe ou le module contient suffisamment de caractéristiques de l'abstraction pour permettre une interaction pertinente et efficace. Faire autrement rendrait le composant inutile. Par exemple, si nous étudions la classe Ensemble, il est sage d'y inclure une opération qui enlève un élément à l'ensemble, mais notre sagesse devient de la futilité si nous oublions d'inclure une opération qui ajouterait un élément. En pratique, les violations de cette caractéristique sont détectées très tôt; de telles imperfections ressortent presque chaque fois que nous construisons un client qui doit utiliser cette abstraction. Complet, indique que l'interface de la classe ou du module contient toutes les caractéristiques pertinentes de l'abstraction. Alors que l'adéquation implique une interface minimale, une interface complète doit couvrir tous les aspects de l'abstraction. Une classe ou un module complet sont tels que leur interface est suffisamment générale pour être utilisable par n'importe quel client. La complétude est une question subjective. Les opérations primitives sont celles qui ne peuvent être offertes efficacement que si on leur donne accès à la représentation sous-jacente de l'abstraction. Ainsi, l'opération consistant à ajouter un élément à un ensemble est primitive car, pour écrire cette opération Add, la représentation sous-jacente doit être visible. D'un autre côté, une opération ajoutant quatre éléments à un ensemble n'est pas primitive, puisqu'elle peut être proposée aussi efficacement à partir de l'opération Add qui est plus primitive - sans avoir accès à la représentation sous-jacente.

Page 50: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 50/58

Diapositive 37

25/03/2001 Cours B4: Programmation et développement orientés objets 37/42

Choix des opérationsSémantique fonctionnelle

RéutilisationComplexitéFacilité d’applicationConnaissance de la mise en œuvre

Sémantique de temps et d’espaceSynchroneDérobanteAvec délaiAsynchrone

Construire l'interface d'une classe ou d'un module est un travail difficile. En général, nous faisons une première tentative de conception d'une classe et ensuite, lorsque nous, ou d'autres développeurs, créons des clients, nous constatons qu'il est nécessaire d'augmenter, de modifier et de perfectionner cette interface. Finalement, nous découvrons parfois des configurations d'opérations ou des configurations d'abstractions qui nous conduisent à inventer de nouvelles classes ou à réorganiser les relations entre classes existantes. A l'intérieur d'une classe donnée, nous préférons que toutes les opérations soient primitives, afin que chacune adopte un comportement limité et bien défini. Nous disons que de telles méthodes ont une granularité fine. De cette façon, il est beaucoup plus facile de construire des sous-classes qui peuvent redéfinir de façon pertinente le comportement de leurs super-classes. La décision de proposer un comportement en une ou plusieurs méthodes peut être faite pour deux raisons contradictoires : condenser un comportement particulier dans une seule méthode conduit à une interface plus simple mais à des méthodes plus grosses et plus complexes ; distribuer un comportement entre plusieurs méthodes conduit à une interface plus compliquée mais à des méthodes plus simples. un bon concepteur sait trouver l'équilibre approprié entre trop distribuer, ce qui induit la fragmentation, et trop peu, ce qui conduit à de gros modules ingérables. En conception orientée objets, il est courant d'étudier les méthodes d'une classe comme un tout, car ces méthodes coopèrent pour former le protocole de l'abstraction. Etant donné un comportement désiré, nous devons décider dans quelle classe il convient de le placer. On utilise les critères de Réutilisation : Ce comportement serait-il utile dans plus d'un contexte ? Complexité: Est-il difficile d'offrir le comportement ?

Page 51: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 51/58

Facilité d'application: Le comportement se rapporte-t-il bien au type dans lequel il pourrait être placé ? Connaissance de la mise en œuvre: La mise en rouvre du comportement dépend-elle des détails internes d'un type ? Nous choisissons habituellement de déclarer les opérations significatives que nous pouvons réaliser sur un objet comme des méthodes dans la définition de la classe (ou de la super-classe) de cet objet. Dans des langages comme C++ on peut aussi déclarer ces opérations comme des sous-programmes libres, groupés dans des utilitaires de classe. Dans la terminologie C++, un sous-programme libre est une fonction non-membre. Comme ils ne peuvent pas être redéfinis, ils sont moins généraux. Cependant, les utilitaires nous aident à garder une classe primitive et à réduire le couplage entre classes, notamment si ces opérations de plus haut niveau concernent des objets de nombreuses classes différentes. Dès que nous avons établi l'existence d'une opération particulière et défini sa défintion fonctionnelle, nous devons prendre des décisions au sujet de sa sémantique de temps et d'espace. Ceci signifie que nous devons spécifier nos choix de conception au sujet du temps nécessaire pour achever une opération et au sujet de la quantité de mémoire nécessaire. De telles décisions sont souvent exprimées en termes de cas meilleur, moyen et pire, ce dernier précisant la limite supérieure de ce qui est acceptable. Lorsqu’un objet passe un message à un autre le long d'un lien, ces deux objets doivent être synchronisés d'une façon quelconque. En présence de flots de contrôle multiples, cela signifie que la transmission de messages est bien plus qu'un simple appel de sous-programme. Dans la plupart des langages que nous utilisons, la synchronisation entre objets ne constitue pas un problème car nos programmes ne contiennent qu'un flot de contrôle, ce qui signifie que tous les objets sont séquentiels. Dans les langages qui supportent la simultanéité, nous devons nous préoccuper de formes plus sophistiquées de transmission de messages, afin d'éviter les problèmes lorsque deux flots de contrôle agissent sans aucune retenue sur le même objet. Les objets dont la sémantique est préservée en présence de multiples flots de contrôle sont soit protégés, soit synchronisés. Il est utile d'exprimer la sémantique de la simultanéité pour chaque opération individuelle ainsi que pour l'objet comme un tout, puisque des opérations différentes peuvent nécessiter différents genres de synchronisation. La transmission de messages peut donc prendre l'une des formes suivantes Synchrone Une opération commence seulement quand l'émetteur a initialisé l'action et le récepteur est prêt à accepter le message; l'émetteur et le récepteur attendront indéfiniment jusqu'à ce que les deux parties soient prêtes à agir. Dérobante Comme pour la forme synchrone, excepté que l'émetteur abandonnera l'opération si le récepteur n'est pas prêt immédiatement. Avec délai Comme pour la forme synchrone, excepté que l'émetteur attendra pendant un laps de temps donné que le récepteur soit prêt. Asynchrone Un émetteur peut initialiser une action sans se soucier de savoir si le récepteur est prêt à recevoir le message.

Page 52: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 52/58

Diapositive 38

25/03/2001 Cours B4: Programmation et développement orientés objets 38/42

Choix des relationsIl est lié au choix des opérationsLes méthodes d’une classe ne doivent pas dépendre de la structure d’aucune autre classe exceptée sa super-classeLes méthodes d’une classe ne doivent envoyer des messages qu’à un nombre très limité de classesDeux types de structures

Hiérarchie large et superficielleHiérarchie étroite et profonde

Si nous décidons que l'objet X envoie un message M à l'objet Y, alors, directement ou indirectement, X doit être visible de Y. Sinon nous ne pourrions pas nommer l'opération M dans le corps de la classe de X. Visible veut dire la possibilité, pour une abstraction, d'en voir une autre et de désigner les ressources de sa vue externe. Les abstractions sont visibles l'une de l'autre seulement lorsqu'elles disposent des droits d'accès adéquats (par exemple, les parties privées d'une classe ne sont accessibles qu'à la classe et à ses amies). Le couplage est donc une mesure du degré de visibilité. Une ligne de conduite utile pour le choix des relations entre objets s'appelle la loi de Demeter, qui dit que «les méthodes d'une classe ne devraient dépendre en aucune façon de la structure de n'importe quelle classe, excepté pour la structure immédiate (au sommet) de leur propre classe. De plus, chaque méthode ne devrait envoyer des messages qu'à des objets appartenant à un ensemble très limité de classes». L'effet fondamental de l'application de cette loi est la création de classes faiblement couplées, dont les secrets de mise en oeuvre sont encapsulés. En examinant la structure de classes d'un système complet, on peut découvrir que sa hiérarchie d'héritage est soit large et superficielle, soit étroite et profonde, soit équilibrée. Les structures de classes larges et superficielles représentent habituellement des forêts de classes indépendantes qui peuvent être mélangées et appariées. Les structures de classes étroites et profondes représentent des arbres de classes reliées par un ancêtre commun. Chaque approche a ses avantages et ses inconvénients. Les forêts de classes sont plus faiblement couplées, mais elles n'exploitent pas toujours toutes les similarités existantes. Les arbres de classes exploitent ces similarités, si bien que les classes individuelles sont plus petites que dans les forêts. Cependant, pour appréhender une classe

Page 53: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 53/58

particulière, il est habituellement nécessaire de comprendre la signification de toutes les classes dont elle hérite ou qu'elle utilise. La forme optimale d'une structure de classes dépend fortement du problème. On doit faire des compromis entre l'héritage, l'agrégation et les relations d'utilisation. Par exemple, la classe voiture doit-elle hériter des classes Moteur et Roue, ou les utiliser? Dans ce cas, une relation d'utilisation est plus appropriée qu'une relation d'héritage. l'héritage est adéquat si chaque instance de B peut aussi être vue comme une instance de A. La relation de client est adéquate quand chaque instance de B possède simplement un ou plusieurs attributs de A D'un autre point de vue, si le comportement d'un objet est plus que la somme de ses parties individuelles, alors la création d'une relation d'utilisation plutôt que d'une relation d'héritage entre les classes appropriées est probablement supérieure.

Page 54: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 54/58

Diapositive 39

25/03/2001 Cours B4: Programmation et développement orientés objets 39/42

Choix des mises en oeuvreRéalisés après avoir complété la conception de la vue extérieure d’une classeImpliquent deux décisions de conception:

Représentation des classes ou des objetsPlacement des classes et des objets dans les modules

La représentation d'une classe ou d'un objet doit presque toujours être l'un des secrets encapsulés de l'abstraction. Ceci rend possible le changement de la représentation (par exemple le changement de la sémantique de temps et d'espace) sans violer aucune des hypothèses fonctionnelles que les clients peuvent avoir faites. le choix d'une représentation est souvent difficile. Il doit toujours être décidé à la lumière des opérations devant être réalisées sur les données. Par exemple, étant donnée une classe dont les objets dénotent un ensemble d'informations de plans de vol, est-ce que nous optimisons la représentation pour une recherche rapide ou pour une insertion et une annulation rapides? Ne pouvant faire les deux, nous devons choisir selon l'utilisation attendue de ces objets. Parfois, il n'est pas facile de choisir, et nous finissons par avoir des familles de classes dont les interfaces sont virtuellement identiques mais dont les mises en oeuvre sont radicalement différentes, afin de procurer un comportement différent dans le temps et dans l'espace. L'un des compromis les plus difficiles, dans le choix de la mise en oeuvre d'une classe, est entre le calcul de la valeur d'un attribut d'un objet ou son stockage en tant que champ. Exemple calculer de la surface d’une figure.Si nous voulons que cette méthode soit rapide, nous devons stocker la surface comme un champ. Si la place mémoire est prioritaire, nous devons calculer la valeur. La meilleure représentation dépend donc fortement du problème considéré. Dans tous les cas, nous devons être capable de choisir une représentation indépendante de la vue externe de la classe ; en fait, nous devrions même être capable de changer cette représentation sans que ses clients s'en rendent compte. Placement d'une classe ou d'un objet. Des questions similaires se posent pour la déclaration des classes et objets à l'intérieur des modules.

Page 55: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 55/58

Les exigences contradictoires de visibilité et d'occultation de l'information guident en général les décisions de conception au sujet de l'endroit où doivent être déclarés les classes et les objets. Habituellement, nous cherchons à construire des modules fonctionnellement cohérents et faiblement couplés. De nombreux facteurs non techniques influencent ces décisions, comme le réemploi, la sécurité et la documentation.

Page 56: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 56/58

Diapositive 40

25/03/2001 Cours B4: Programmation et développement orientés objets 40/42

Résumé (1/3)Un objet a un état, un comportement et une identité.La structure et le comportement d'objets similaires sont définis dans leur classecommune.L'état d'un objet englobe toutes les propriétés (statiques) de l'objet, ainsi que les valeurs courantes (dynamiques) de chacune de ces propriétés.Le comportement est la façon dont un objet agit et réagit en termes de changementsd'état et de passage de messages.

Page 57: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 57/58

Diapositive 41

25/03/2001 Cours B4: Programmation et développement orientés objets 41/42

Résumé (2/3)L'identité est la propriété d'un objet qui le distingue de tous les autres objets.Les deux genres de hiérarchies d'objets comprennent les liens et les agrégations.Une classe est un ensemble d'objets qui partagent une structure et un comportementcommuns.Les cinq types de hiérarchies de classes sont l'association, l'héritage, l'agrégation,l'utilisation, l'instanciation.

Page 58: Programmation et Développement orientés objetssuffi.free.fr/poo/03-Classes.pdf · Chapitre 3 Cours B4 : Programmation et Développement OO 2/58 ... Programmation et développement

Chapitre 3 Cours B4 : Programmation et Développement OO 58/58

Diapositive 42

25/03/2001 Cours B4: Programmation et développement orientés objets 42/42

Résumé (3/3)Les abstractions fondamentales sont les classes et les objets qui forment le vocabulaire du domaine du problème.Un mécanisme est une structure au moyen de laquelle un ensemble d'objets travaillent ensemble pour délivrer un comportement qui satisfait certaines exigences du problème.La qualité d'une abstraction peut être mesurée par son couplage, sa cohérence, son adéquation, sa complétude et saprimitivité.