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

Interface

Pour permettre à un code extérieur de manipuler un objet Rectangle ou Carre et par exemple demander sa surface ou son périmètre, sans avoir besoin de savoir si c'est un rectangle ou un carré, il faut créer une interface commune, par exemple FormeCarre et Rectangle devront déclarer qu'elles implémentent cette interface.