7.3Différences entre classes abstraites et interfaces
7.3 – Différences entre classes abstraites et interfaces
Les classes abstraites et les interfaces sont deux mécanismes similaires mais avec des différences importantes. Comprendre ces différences est crucial pour choisir le bon outil selon le contexte.
📊 Tableau de comparaison détaillé
| Caractéristique | Classe abstraite | Interface |
|---|---|---|
| Héritage | Simple (une seule classe avec extends) | Multiple (plusieurs interfaces avec implements) |
| Attributs | Peut avoir des attributs d'instance (non final) | Seulement des constantes (public static final) |
| Méthodes concrètes | Oui (peut avoir des méthodes avec implémentation) | Oui (depuis Java 8 avec default et static) |
| Méthodes abstraites | Peut avoir des méthodes abstraites | Toutes les méthodes sont abstraites par défaut (sauf default/static) |
| Constructeurs | Oui (peut avoir des constructeurs) | Non (pas de constructeurs) |
| Modificateurs d'accès | Tous (public, protected, private, package-private) | Seulement public (implicite) |
| Instanciation | Non (ne peut pas être instanciée) | Non (ne peut pas être instanciée) |
| Mot-clé | abstract class | interface |
| Héritage de classe | extends | implements |
🔍 Différences détaillées
1. Héritage
Classe abstraite : Héritage simple
public abstract class Animal {
// ...
}
// Une classe ne peut hériter que d'une seule classe abstraite
public class Chien extends Animal {
// ...
}
Interface : Implémentation multiple
public interface Drawable {
void draw();
}
public interface Colorable {
void setColor(String color);
}
// Une classe peut implémenter plusieurs interfaces
public class Cercle implements Drawable, Colorable {
// ...
}
2. Attributs
Classe abstraite : Attributs d'instance
public abstract class Animal {
protected String nom; // Attribut d'instance
private int age; // Attribut privé
public static int compteur; // Attribut statique
}
Interface : Seulement des constantes
public interface Configuration {
// Seulement des constantes (public static final implicite)
int MAX_SIZE = 100;
String DEFAULT_COLOR = "BLACK";
// ❌ ERREUR : pas d'attributs d'instance
// String nom;
}
3. Constructeurs
Classe abstraite : Peut avoir des constructeurs
public abstract class Animal {
protected String nom;
public Animal(String nom) { // Constructeur
this.nom = nom;
}
}
public class Chien extends Animal {
public Chien(String nom) {
super(nom); // Appelle le constructeur de Animal
}
}
Interface : Pas de constructeurs
public interface Drawable {
// ❌ ERREUR : pas de constructeurs
// public Drawable() { }
}
đź’ˇ Quand utiliser une classe abstraite ?
Utilisez une classe abstraite quand :
- Vous avez du code commun Ă partager entre plusieurs classes
- Vous avez besoin d'attributs d'instance non constants
- Vous avez besoin de constructeurs
- Vous voulez définir des méthodes avec des modificateurs d'accès autres que public
- Vous créez une hiérarchie de classes avec une relation "est-un" forte
Exemple : Classe abstraite appropriée
// Hiérarchie de véhicules avec code commun
public abstract class Vehicule {
protected String marque; // Attribut partagé
protected int annee; // Attribut partagé
public Vehicule(String marque, int annee) { // Constructeur
this.marque = marque;
this.annee = annee;
}
// Méthode concrète partagée
public void afficherInfo() {
System.out.println(marque + " - " + annee);
}
// Méthode abstraite à implémenter
public abstract void demarrer();
}
đź’ˇ Quand utiliser une interface ?
Utilisez une interface quand :
- Vous voulez définir un contrat que plusieurs classes non liées doivent respecter
- Vous avez besoin d'implémentation multiple
- Vous définissez des capacités ou des comportements (Drawable, Flyable, etc.)
- Vous voulez une séparation claire entre le contrat et l'implémentation
- Vous travaillez avec des API où l'implémentation peut varier
Exemple : Interface appropriée
// Capacité que plusieurs classes peuvent avoir
public interface Drawable {
void draw();
}
// Différentes classes non liées peuvent être Drawable
public class Cercle implements Drawable { }
public class Rectangle implements Drawable { }
public class Texte implements Drawable { }
🔄 Combinaison : Classe abstraite + Interface
Vous pouvez combiner les deux approches pour bénéficier des avantages de chacune.
Exemple : Combinaison classe abstraite et interface
// Interface pour une capacité
public interface Drawable {
void draw();
}
// Classe abstraite pour le code commun
public abstract class Forme implements Drawable {
protected String couleur;
public void setCouleur(String couleur) {
this.couleur = couleur;
}
}
// Classe concrète
public class Cercle extends Forme {
@Override
public void draw() {
System.out.println("Dessine un cercle " + couleur);
}
}
💡 Points clés à retenir
- Classe abstraite : Pour partager du code et créer une hiérarchie "est-un"
- Interface : Pour définir des contrats et des capacités
- Héritage : Simple pour classes abstraites, multiple pour interfaces
- Attributs : Instance pour classes abstraites, constantes pour interfaces
- Constructeurs : Oui pour classes abstraites, non pour interfaces
- Combinaison : Vous pouvez utiliser les deux ensemble
- Si vous hésitez, préférez une interface si vous n'avez pas besoin de partager du code
- Utilisez une classe abstraite si vous avez beaucoup de code commun Ă partager
- Les interfaces sont plus flexibles (implémentation multiple)
- Les classes abstraites sont plus puissantes (constructeurs, attributs, modificateurs)
- En général : "Interface pour ce qu'un objet peut faire, classe abstraite pour ce qu'un objet est"