Un classe abstraite est une classe que l'on ne peut pas instancier. Elle est destinée uniquement à servir de base à des classes dérivées. Une classe abstraite peut contenir des membres et des méthodes implémentées, ou des méthodes abstraites (cf. plus bas).
Pour les objets géométriques, la classe mère
Dans le code ci-dessous, le mot-clé abstract déclare la classe
public abstract class GeomObject { private static int nbCreatedObjects = 0; private String objName = null; private static AbstractColor defaultColor = ReferenceColor.BLACK; private AbstractColor objColor = null; public GeomObject () { nbCreatedObjects++; setObjName("anonymous_" + String.valueOf(nbCreatedObjects)); } // GeomObject () public String getObjName() { return objName; } // getObjName() public void setObjName (String objName) { this.objName = objName; } // setObjName() public String toString () { return getObjName() + " [GeomObj]"; } // toString () public void setObjColor (AbstractColor objColor) { this.objColor = objColor; } // setObjColor () public AbstractColor getObjColor () { return objColor; } // getObjColor () } // on ne peut pas instancier d'objet de type Point public abstract class Point extends GeomObject { // ... } // mais on peut instancier un objet de type MobilePoint public abstract class MobilePoint extends Point { // ... }
Note : même si l'on ne peut pas instancier d'objet d'une classe abstraite,
on peut implémenter un constructeur pour ce type de classe.
Ce constructeur est exécuté par invocation de
Par exemple, on a vu qu'on ne pouvait pas instancier la classe
Dans une classe abstraite, on peut ajouter la signature (nom, type de retour et liste du type des arguments) d'une méthode déclarée abstraite. Cela veut dire qu'une classe dérivée devra implémenter cette méthode pour ne plus être abstraite.
Par exemple, imaginons que l'on veuille calculer, pour chaque type d'objet graphique,
l'étendue horizontale (sur l'axe des abscisses) et l'étendue verticale (sur l'axe des ordonnées)
de l'objet. Pour les objets de type cercle, segment et point, c'est simple.
Mais pour un groupe, cela nécessite de connaître le point le plus à gauche (l'abscisse minimale)
et le plus à droite (l'abscisse maximale) des objets de ce groupe dans le repère
ainsi que le point le plus bas (l'ordonnée minimale) et le plus haut (l'ordonnée maximale)
des objets de ce groupe dans le repère.
On décide d'ajouter les méthodes D'une part, on veut contraindre toutes les classes "concrètes" qui dérivent de public abstract class GeomObject { private String objName = null; // ... public GeomObject () { nbCreatedObjects++; setObjName("anonymous_" + String.valueOf(nbCreatedObjects)); } // GeomObject () public String toString () { return getObjName() + " [GeomObj]"; } // toString () public abstract int getMaxX (); public abstract int getMinX (); public abstract int getMaxY (); public abstract int getMinY (); } |
Illustration : calcul de l'étendue horizontale d'un goupe |
La méthode
Si, dans la classe
Nouvelle classe
public class Circle extends GeomObject { private MobilePoint center = null; private int radius; // ... public int getMaxX () { return getCenter().getX() + getRadius(); } public int getMinX () { return getCenter().getX() - getRadius(); } public int getMaxY () { return getCenter().getY() + getRadius(); } public int getMinY () { return getCenter().getY() - getRadius(); } }
Dans une classe abstraite, une méthode peut invoquer, dans son implémentation,
une méthode déclarée abstraite. C'est par exemple le cas
des méthodes
public abstract class GeomObject { // ... public abstract int getMaxX (); public abstract int getMinX (); public abstract int getMaxY (); public abstract int getMinY (); public int getHorizontalSpan () { return getMaxX() - getMinX(); } // getHorizontalSpan () public int getVerticalSpan () { return getMaxY() - getMaxY(); } // getVerticalSpan () }