|

Écrivez
à AILES ! |

Retour
vers programmation |

Retour
vers les questions Objet |

Retour vers les
questions sur les
Héritage et Association |
|
|
Questionnaire Objet
Héritage
et Association
[IngeObjet], [WikiWikiWeb], [Guyot]
|
Hormis la classique différence
'est-un' (héritage) - 'a-un' (association), il est
intéressant de bien garder à l'esprits les enjeux de
l'utilisation de ces relations entre objets. |
Héritage
et association :
Si l'on considère une modélisation avec
peu d'héritages, on peut obtenir une modélisation du genre :
 |
Il s'agit d'une vision dynamique
où, notamment pour la Femme, toutes ses caractéristiques
(age, mariage, maternité) ne peuvent être déterminées
qu'à l'exécution du programme.
D'où la nécessité de spécifier des
invariants complets (et complexes) au niveau de l'objet
'Femme' |
Dans cette vision dynamique, les associations
permettent de faire jouer plusieurs rôles (ou niveaux
fonctionnels) à une même
entité. Ces rôles peuvent évoluer dans le temps.
Cette évolution dans le temps constitue l'aspect dynamique d'une
association.
Ainsi, une femme majeure célibataire peut à tout moment devenir une
femme mariée via l'association mariage.
L'intérêt est de pouvoir étendre facilement le modèle sans
remettre en cause le découpage statique 'Homme' - 'Femme' imposé par
les 2 relations d'héritages. Par exemple, une 'Personne' peut se voir
adjoindre l'attribut 'salaire annuel', accompagné d'un invariant sur
l'age (seules les personnes majeures travaillent). Cet attribut sera
valable pour toutes les instances d''Homme' et 'Femme'.
Si l'on tire parti des propriétés de
classification de l'héritage, on peut modéliser la même société
ainsi.
 |
Ce découpage permet statiquement
de classifier les différents rôles attribués à l'objet
'Femme'.
En revanche, les rôles ainsi mise en
évidence sont figés dans le temps (d'où
l'aspect statique).
Une conséquence de ce rôle statique est
de permettre la diminution de la cardinalité des associations
: une 'FemmeAdulte' a un (et un seul) mari, au lieu de '0 ou
un' dans la précédente modélisation.
L'autre conséquence concerne les
invariants, moins nombreux (et moins complexes). Le rôle
étant simplifié (le niveau fonctionnel étant diminué), il
y a moins de contrôles dynamiques à réaliser, notamment
entre 'FemmeAdulte' et 'Mère'. |
Dans cette vision dynamique, les
objets sont plus facile à manipuler (rien que le type permet de
savoir "à qui l'on a à faire", ce qui permet de détecter
dès la compilation des incohérences, plutôt que de s'en remettre à
des invariants, source de bugs potentiels et qui peuvent impacter les
performances d'un programme).
Ces mêmes objets sont plus faciles à gérer, car
leur rôle est simplifié.
En revanche, toute évolution dans le temps sera
plus dure à modéliser. L'attribut 'salaire annuel' ne peut plus
s'appliquer à 'Personne', mais doit se retrouver dupliquer entre
'Homme' (avec un invariant) et 'FemmeAdulte'... Si la modélisation
faisaient apparaître beaucoup d'autres propriétés dynamiques, cela
serait un argument pour revenir au premier style de modélisation,
plus orienté 'association' que 'héritage'.
Manipulation de plusieurs objets
comme une seule entité
Cette manipulation est naturelle avec l'héritage,
qui suit le principe de substitution de Liskow ([Guyot])
:
Si A 'est un' B,
Alors il doit être possible de substituer à un objet de la classe la
plus générale (B) un objet d'une de ses sous-classes (A) sans
modifier le comportement du système (le programme).
Ainsi, une collection (ou liste) de 'Personne'
représentation une collection d''Homme' ou de 'Femme', toutes
manipulées comme l'entité 'Personne' (donc avec les seuls
propriétés - attributs, méthodes - de 'Personne').
Pour les association, une telle manipulation se
retrouve uniquement avec la composition
(ou agrégation de composition) ([IngeObjet]),
qui permet la création d'objets à partir de l'agrégation d'autres
objets. Un objet obtenu est un objet composé et ses sous-objets sont
des objets composants. Les liens unissant les objets composants à
l'objet composé sont matérialisés par une hiérarchie d'objets dont
le somme est l'objet composé. Il s'agit d'une approche ascendante de
la composition, dans laquelle les objets de plus bas niveau
transmettent leurs attributs aux objets de plus haut niveau dans la
hiérarchie de composition.
Ainsi, une Voiture, composée d'une Carrosserie,
elle même composée d'un Toit pourra voir l'attribut 'couleur' du
Toit propagé à Carrosserie et même à Voiture : peindre la Voiture
intégralement en 'bleu' impactera la couleur de la Carrosserie et du
Toit.
La première solution, basée sur l'héritage,
entraîne une forte augmentation des types d'objets, alors que la
solution basée sur les associations et en particulier la composition
diminue ce nombre de type, mais complexifie les concepts représentés
(Voiture, Carrosserie et Toit ont chacun leur attribue 'couleur' et il
faudra géré leur cohérence, surtout lorsque l'on implémente la
fonction 'peindre' de Voiture...).
Hiérarchies au sein d'un objet
[IngeObjet]
Si l'on se limite à l'objet,
on distingue sa partie interne (définie par la classe)
de la partie externe (défini par le type de la classe)
La partie interne de l'objet se matérialise
par :
- un ensemble d'associations 'a un' liant les attributs et les
opérations (issue via une hiérarchie de classe,
cf. héritage de classe)
- une hiérarchie d'objets liés par des relations de composition
(forme particulière d'association, de type
'est partie de'). Les
propriétés des sous-objets composants sont transmis à l'objet
composé.
La Voiture représente la racine d'une hiérarchie d'objet obtenue par
composition d'une Carrosserie, d'un Moteur et de Roues.
La partie externe de l'objet représente son environnement
conceptuel, en particulier son type et les relations de
généralisation/spécialisation. Ces relations sont
représentées par une hiérarchie de types d'objet établissant un
héritage simple descendant d'un type générique vers des sous-types
spécialisés.
Donc, au delà des réponses évidentes
(hiérarchie de classe et hiérarchie de type), il ne fallait pas
oublier la hiérarchie d'objet issue des relations de composition.
Combinaison de l'héritage et de la
composition
[IngeObjet]
Les liens de composition
définis dans une classes
sont hérités (avec leurs propriétés) par toutes les
sous-classes de cette classe. Une sous-classe peut aussi bien ajouter
de nouveaux liens de composition ou spécialiser les liens de
composition hérités.
Remarque, on hérite aussi du lien 'partie de', le
lien inverse du lien de composition. Ce lien n'est pas toujours
explicitement représenté. En d'autres termes, le pointeur retour du
composant vers l'objet composite n'est pas toujours défini, afin de
respecter le principe d'indépendance des composants qui stipule que
l'objet composite connaît ses composants mais pas l'inverse. Le
respect de ce principe favorise la modularité et la
réutilisabilité.
Héritage ou association ?
Si l'on s'en tient aux associations en général,
les avantages et inconvénients ont déjà été mentionnés dans la première réponse. L'aspect statique ou dynamique
dans le temps des propriétés d'un objet est impacté par le choix de
l'une ou l'autre des relations.
Si l'on considère la relation de composition, on
trouvera dans [WikiWikiWeb]
tous les moyens nécessaires pour utiliser la composition à la place
de l'héritage.
L'argument majeur est de rendre explicite au travers de la composition
le choix de fonctionnalité que l'on attendait de l'héritage : soit
on voulait le polymorphisme, ou alors la centralisation des
propriétés (plus rarement les deux).
En utilisant des interfaces et des liens de
composition, le code devient plus facile à modifier ("refactor"):
il n'y a plus de lien statique (c.à.d. présent dès la compilation)
entre une classe et sa classe mère. Les références vers des
fonctionnalités communes deviennent explicites et non obtenues via un
mécanisme implicite d'héritage de type.
|