“doc” (Col. : Science Sup 17x24) — 2007/7/19 — 18:18 — page 272 — #282
i
i
i
i
i
i
i
i
272
6
• La programmation orientée objet
nécessaires pour donner la nouvelle classe. Les langages orientés objet soutiennent
cette transformation en définissant les classes comme une abstraction linguistique. La
transformation peut être vue comme une manipulation syntaxique, où la syntaxe de
la nouvelle classe peut être dérivée des classes originales (voir section 6.3). Dans le
système à objets de ce chapitre, la transformation a aussi un sens sémantique. Comme
les classes sont des valeurs, la transformation peut être vue comme une fonction qui
prend des valeurs de classe comme entrées et qui renvoie un nouvelle valeur de classe
comme sortie.
Quoique prometteur, l’expérience montre que l’héritage est un concept à utiliser
avec beaucoup de prudence. D’abord, la transformation doit être définie avec une
connaissance intime des classes ancêtres, parce qu’elle peut facilement briser un
invariant de classe. Un autre problème est que l’héritage ouvre une nouvelle interface
à un composant. La possibilité d’étendre une classe peut être vue comme une nouvelle
manière d’interagir avec cette classe. Il faut maintenir cette interface pendant toute la
durée de vie du composant. Pour cette raison, le défaut quand on définit une classe
devrait être qu’elle est finale, c’est-à-dire qu’il est interdit pour d’autres classes d’en
hériter. Rendre une classe (ou une partie d’une classe) extensible par l’héritage doit
être une action explicite par le programmeur de la classe.
L’héritage augmente les possibilités de factoriser une application, c’est-à-dire de
faire en sorte que les parties communes n’existent qu’une fois, mais le prix à payer
est que l’implémentation de l’abstraction est étalée sur des parties différentes du
programme. L’implémentation n’existe pas à un endroit précis ; toutes les abstractions
dont elle hérite doivent être considérées ensemble. Cela rend la compréhension de
l’implémentation plus difficile et paradoxalement peut rendre la maintenance plus
difficile. De plus, une abstraction peut hériter d’une classe qui existe seulement en tant
que code compilé, sans aucun accès au code source. L’héritage doit donc être utilisé
avec parcimonie.
Une alternative est d’utiliser la programmation par composants, c’est-à-dire d’utiliser les composants directement et de les composer. L’idée est de définir un composant
qui encapsule un autre composant et qui fournit une fonctionnalité modifiée. Il y a
un choix entre l’héritage et la composition de composants : l’héritage est plus souple
mais il peut briser un invariant de classe, tandis que la composition de composants est
moins souple mais ne peut pas briser un invariant de composant. Ce choix doit être
considéré soigneusement chaque fois qu’il faut étendre une abstraction.
On a pu penser que l’héritage résoudrait le problème du réemploi du logiciel. Il
simplifierait la construction des bibliothèques que l’on pourrait distribuer au tiers,
pour l’utilisation dans d’autres applications. Cet espoir a été partiellement réalisé avec
les cadres d’applications. Un cadre d’applications (« application framework ») est
une plate-forme logicielle qui est générique. Instancier le cadre veut dire donner des
Précédent

- 287/370

Suivant