↑
CHAPITRE 7.2

Interfaces

Définir des contrats que les classes doivent respecter
Une interface définit un contrat que les classes doivent respecter. Elle contient uniquement des déclarations de méthodes (sans implémentation). Une classe peut implémenter plusieurs interfaces.

7.2Interfaces

7.2.1 – Déclaration d'une interface

Une interface est un contrat qui définit un ensemble de méthodes qu'une classe doit implémenter. Contrairement aux classes abstraites, une interface ne peut contenir que des déclarations de méthodes (sans implémentation) et des constantes. Une classe peut implémenter plusieurs interfaces.

🔑 Syntaxe de déclaration

Une interface est déclarée avec le mot-clé interface. Par défaut, toutes les méthodes sont public et abstract.

Exemple : Interface simple

public interface Drawable {
    // Méthode abstraite (public abstract implicite)
    void draw();
    
    // Autre méthode abstraite
    void effacer();
}

📋 Caractéristiques des interfaces

  • Toutes les mĂ©thodes sont public et abstract par dĂ©faut
  • Ne peut contenir que des mĂ©thodes abstraites (avant Java 8) ou des mĂ©thodes par dĂ©faut/statiques (Java 8+)
  • Peut contenir des constantes (public static final par dĂ©faut)
  • Ne peut pas ĂŞtre instanciĂ©e directement
  • Une classe peut implĂ©menter plusieurs interfaces

🆕 Méthodes par défaut (Java 8+)

Depuis Java 8, les interfaces peuvent contenir des méthodes avec une implémentation par défaut en utilisant le mot-clé default.

Exemple : Interface avec méthode par défaut

public interface Drawable {
    // Méthode abstraite (doit être implémentée)
    void draw();
    
    // Méthode par défaut (implémentation fournie)
    default void afficher() {
        System.out.println("Affichage par défaut");
    }
    
    // Méthode statique (Java 8+)
    static void info() {
        System.out.println("Interface Drawable");
    }
}

📊 Constantes dans les interfaces

Les interfaces peuvent contenir des constantes. Par défaut, elles sont public static final.

Exemple : Interface avec constantes

public interface Configuration {
    // Constantes (public static final implicite)
    int MAX_SIZE = 100;
    String DEFAULT_COLOR = "BLACK";
    
    void configurer();
}

// Utilisation des constantes
public class App {
    public static void main(String[] args) {
        System.out.println(Configuration.MAX_SIZE);      // 100
        System.out.println(Configuration.DEFAULT_COLOR);  // BLACK
    }
}

🔄 Interfaces multiples

Une interface peut étendre plusieurs autres interfaces (héritage multiple d'interfaces).

Exemple : Héritage d'interfaces

public interface Drawable {
    void draw();
}

public interface Colorable {
    void setColor(String color);
}

// Interface qui étend plusieurs interfaces
public interface DrawableColorable extends Drawable, Colorable {
    void afficher();
}

7.2.2 – Implémentation d'une interface

Pour utiliser une interface, une classe doit l'implémenter avec le mot-clé implements. La classe doit fournir une implémentation pour toutes les méthodes abstraites de l'interface.

📝 Implémentation simple

Exemple : Implémentation d'une interface

public interface Drawable {
    void draw();
    void effacer();
}

// Classe qui implémente l'interface
public class Cercle implements Drawable {
    private double rayon;
    
    public Cercle(double rayon) {
        this.rayon = rayon;
    }
    
    @Override
    public void draw() {
        System.out.println("Dessine un cercle de rayon " + rayon);
    }
    
    @Override
    public void effacer() {
        System.out.println("Efface le cercle");
    }
}

🔄 Implémentation de plusieurs interfaces

Une classe peut implémenter plusieurs interfaces, ce qui permet une grande flexibilité.

Exemple : Implémentation multiple

public interface Drawable {
    void draw();
}

public interface Colorable {
    void setColor(String color);
    String getColor();
}

public interface Resizable {
    void resize(double factor);
}

// Classe qui implémente plusieurs interfaces
public class Cercle implements Drawable, Colorable, Resizable {
    private String color;
    private double rayon;
    
    @Override
    public void draw() {
        System.out.println("Dessine un cercle " + color);
    }
    
    @Override
    public void setColor(String color) {
        this.color = color;
    }
    
    @Override
    public String getColor() {
        return color;
    }
    
    @Override
    public void resize(double factor) {
        rayon *= factor;
    }
}

đź’ˇ Utilisation polymorphique

Les interfaces permettent également l'utilisation du polymorphisme.

Exemple : Polymorphisme avec interfaces

public interface Drawable {
    void draw();
}

public class Cercle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Dessine un cercle");
    }
}

public class Rectangle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Dessine un rectangle");
    }
}

// Utilisation polymorphique
public class Test {
    public static void main(String[] args) {
        Drawable[] formes = {
            new Cercle(),
            new Rectangle(),
            new Cercle()
        };
        
        for (Drawable forme : formes) {
            forme.draw();  // Polymorphisme
        }
    }
}

🆕 Méthodes par défaut et leur utilisation

Les méthodes par défaut permettent d'ajouter de nouvelles fonctionnalités aux interfaces sans casser le code existant.

Exemple : Méthodes par défaut

public interface Drawable {
    void draw();  // Méthode abstraite
    
    // Méthode par défaut : implémentation fournie
    default void afficher() {
        System.out.println("Affichage par défaut");
        draw();  // Appelle la méthode abstraite
    }
}

public class Cercle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Dessine un cercle");
    }
    
    // afficher() n'a pas besoin d'être redéfinie (utilise la version par défaut)
    // Mais peut être redéfinie si nécessaire
}

// Utilisation
Cercle c = new Cercle();
c.draw();      // Affiche : Dessine un cercle
c.afficher();  // Affiche : Affichage par défaut
               //          Dessine un cercle

📊 Exemple complet : Système de paiement

Exemple : Interface de paiement

public interface Paiement {
    // Constante
    double TAUX_TVA = 0.20;
    
    // Méthode abstraite
    void payer(double montant);
    
    // Méthode par défaut
    default double calculerAvecTVA(double montant) {
        return montant * (1 + TAUX_TVA);
    }
}

public class CarteCredit implements Paiement {
    private String numeroCarte;
    
    public CarteCredit(String numeroCarte) {
        this.numeroCarte = numeroCarte;
    }
    
    @Override
    public void payer(double montant) {
        double montantAvecTVA = calculerAvecTVA(montant);
        System.out.println("Paiement de " + montantAvecTVA + "€ par carte " + numeroCarte);
    }
}

public class Paypal implements Paiement {
    private String email;
    
    public Paypal(String email) {
        this.email = email;
    }
    
    @Override
    public void payer(double montant) {
        double montantAvecTVA = calculerAvecTVA(montant);
        System.out.println("Paiement de " + montantAvecTVA + "€ via PayPal : " + email);
    }
}

💡 Points clés à retenir

  • Interface : Contrat dĂ©finissant des mĂ©thodes Ă  implĂ©menter
  • implements : Mot-clĂ© pour implĂ©menter une interface
  • ImplĂ©mentation multiple : Une classe peut implĂ©menter plusieurs interfaces
  • MĂ©thodes abstraites : Doivent ĂŞtre implĂ©mentĂ©es par les classes
  • MĂ©thodes par dĂ©faut : Fournissent une implĂ©mentation par dĂ©faut (Java 8+)
  • Constantes : Les interfaces peuvent contenir des constantes
  • Polymorphisme : Les interfaces permettent le polymorphisme
Conseils pratiques :
  • Utilisez des interfaces pour dĂ©finir des contrats que plusieurs classes peuvent respecter
  • Les interfaces sont idĂ©ales pour dĂ©finir des capacitĂ©s (Drawable, Flyable, etc.)
  • L'implĂ©mentation multiple permet Ă  une classe d'avoir plusieurs capacitĂ©s
  • Les mĂ©thodes par dĂ©faut permettent d'Ă©tendre les interfaces sans casser le code existant
  • PrĂ©fĂ©rez les interfaces aux classes abstraites quand vous n'avez pas besoin de partager du code