Rectangle
Cet exemple a pour but de montrer les différentes
méthodes possibles pour réutiliser le code d'une classe,
ici la classe Rectangle
, avec leurs avantages et leurs
inconvénients. Le but de cette réutilisation est de
rajouter une classe Carre
.
Héritage
La première solution consiste à considérer, comme
en mathématique, qu'un carré est un rectangle, avec pour
contrainte que la hauteur et la largeur doivent toujours rester
égales. La classe Carre
sera donc une sous-classe de la classe Rectangle
.
Cette solution n'est pas satisfaisante. Une sous-classe doit pouvoir
respecter tous les "contrats" de la sur-classe, car tout objet de la
sous-classe est également un objet de la sur-classe. Or parmi
les contrats de Rectangle
, il doit être possible de
définir des hauteurs et largeurs différentes. La
méthode Rectangles.doublerRectangle(Rectangle
r)
démontre que cette solution n'est pas correcte :
appliquée à un carré, les dimensions ne seront pas
doublées, mais quadruplées, comme on peut le voir dans la
classe Test
.
Utilisation d'une classe abstraite
La seconde solution utilise également l'héritage, mais
cette fois-ci de façon interne au paquetage. Rectangle
et Carre
factorisent leur code dans une classe abstraite RectangleAbstrait
dont l'usage est limité au paquetage rectangle
. A
noter que cette limitation n'a de sens que si le client n'a pas de
raison de définir ses propres sous-classes de RectangleAbstrait
.
Dans le cas contraire, la limitation de la visibilité de RectangleAbstrait
entraînera une limitation de la ré-utilisabilité du
code, ce qui n'est pas souhaitable. L'inconvénient de cette
solution est l'usage d'une classe supplémentaire (code plus
complexe). De plus, utiliser l'héritage n'est pas toujours
possible si l'une des classes (et pas l'autre) doit déjà
hériter d'une autre classe. En effet, l'héritage multiple
est interdit en Java.
Délégation
La dernière solution proposée utilise la
délégation. La délégation est un usage
particulier de l'agrégation, consistant à faire faire
tout ou partie du "travail" à un autre objet. Ici, une instance
de Carre
délègue à une instance de Rectangle
.
Un des avantages majeurs de la délégation par rapport
à l'héritage est qu'il est compatible avec la
dérivation. Dans l'exemple présenté, cela signifie
que si l'on décide de dériver Rectangle
en
sous-classes, par exemple Rectangle1
et Rectangle2
,
on pourra dans l'exemple par délégation utiliser ces
sous-classes dans Carre
: il suffit de remplacer
l'instruction
delegue = new Rectangle(taille, taille);
par, par exemple
delegue = new Rectangle1(taille, taille);
Si Carre hérite de Rectangle ou de RectangleAbstrait, il sera
nécessaire de créer de nouvelles classes, RectangleAbstrait1
,
Carre1
…