Default et Static dans les Interfaces
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 37 sur 87.
À l'origine, les interfaces ne pouvaient contenir que des méthodes abstraites sans implémentation. À partir de Java 8, les interfaces ont acquis la capacité d'inclure des méthodes par défaut et des méthodes statiques, ce qui les rend plus flexibles.
Une méthode par défaut fournit une implémentation directement dans l'interface en utilisant le mot-clé default. Les classes qui implémentent l'interface héritent automatiquement de ce comportement mais peuvent le redéfinir si nécessaire :
public interface Drawable {
void draw();
default void display() {
System.out.println("Displaying on screen...");
draw();
}
}Toute classe implémentant Drawable obtient la méthode display() gratuitement. Ceci est particulièrement utile pour ajouter de nouvelles méthodes à des interfaces existantes sans casser les classes qui les implémentent déjà.
Les méthodes statiques dans les interfaces fonctionnent comme les méthodes statiques dans les classes. Elles appartiennent à l'interface elle-même et sont appelées en utilisant le nom de l'interface :
public interface MathOperations {
static int add(int a, int b) {
return a + b;
}
}
// Utilisation
int result = MathOperations.add(5, 3);Les méthodes d'interface statiques ne peuvent pas être redéfinies et ne sont pas héritées par les classes d'implémentation. Elles sont utiles pour les méthodes utilitaires liées à l'objectif de l'interface.
Si une classe implémente deux interfaces avec la même signature de méthode par défaut, la classe doit redéfinir cette méthode pour résoudre le conflit.
Défi
FacileConstruisons un système de messagerie qui met en avant à la fois les méthodes par défaut (default) et statiques dans les interfaces. Vous allez créer une interface avec des fonctionnalités intégrées que les classes d'implémentation peuvent utiliser directement ou personnaliser selon leurs besoins.
Vous organiserez votre code sur quatre fichiers :
Messenger.java: Définissez une interface qui représente n'importe quel service de messagerie. Elle doit déclarer une méthode abstraitesendMessage(String message)qui ne retourne rien (void). Ajoutez une méthode par défaut appeléesendWithTimestamp(String message)qui affiche :[TIMESTAMP]suivi de l'appel àsendMessage(message). Incluez également une méthode statique appeléeformatMessage(String message)qui retourne le message converti en majuscules.EmailMessenger.java: Créez une classe qui implémenteMessenger. Elle possède un champrecipient(String). Incluez un constructeur pour initialiser le destinataire. ImplémentezsendMessage()pour afficher :Email to [recipient]: [message]. Cette classe utilise la méthode par défautsendWithTimestamp()telle quelle.SMSMessenger.java: Créez une autre classe qui implémenteMessenger. Elle possède un champphoneNumber(String). Incluez un constructeur pour initialiser le numéro de téléphone. ImplémentezsendMessage()pour afficher :SMS to [phoneNumber]: [message]. Surchargez la méthode par défautsendWithTimestamp()pour afficher :[URGENT]suivi de l'appel àsendMessage(message)au lieu d'utiliser le comportement d'horodatage par défaut.Main.java: Rassemblez tout pour démontrer les méthodes d'interface par défaut et statiques. Vous recevrez trois entrées : un destinataire d'e-mail, un numéro de téléphone et un message. Tout d'abord, utilisez la méthode statiqueMessenger.formatMessage()pour formater le message et le stocker. Ensuite, créez un EmailMessenger et un SMSMessenger. Pour chaque messager, appelezsendWithTimestamp()avec le message formaté — remarquez comment l'EmailMessenger utilise l'implémentation par défaut tandis que le SMSMessenger utilise sa version surchargée.
Vous recevrez trois entrées : le destinataire de l'e-mail (String), le numéro de téléphone (String) et le message (String).
Votre sortie devrait afficher quatre lignes au total — deux pour chaque messager. L'EmailMessenger affichera le préfixe d'horodatage par défaut, tandis que le SMSMessenger affichera son préfixe urgent personnalisé. Les deux utiliseront le message formaté statiquement (en majuscules) !
Aide-mémoire
À partir de Java 8, les interfaces peuvent inclure des méthodes par défaut et des méthodes statiques en plus des méthodes abstraites.
Les méthodes par défaut fournissent une implémentation directement dans l'interface en utilisant le mot-clé default. Les classes qui implémentent l'interface héritent automatiquement de ce comportement mais peuvent le surcharger si nécessaire :
public interface Drawable {
void draw();
default void display() {
System.out.println("Displaying on screen...");
draw();
}
}Les méthodes statiques dans les interfaces appartiennent à l'interface elle-même et sont appelées en utilisant le nom de l'interface. Elles ne peuvent pas être surchargées et ne sont pas héritées par les classes d'implémentation :
public interface MathOperations {
static int add(int a, int b) {
return a + b;
}
}
// Utilisation
int result = MathOperations.add(5, 3);Si une classe implémente deux interfaces avec la même signature de méthode par défaut, la classe doit surcharger cette méthode pour résoudre le conflit.
Essayez vous-même
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lire les entrées
String emailRecipient = scanner.nextLine();
String phoneNumber = scanner.nextLine();
String message = scanner.nextLine();
// TODO: Utiliser Messenger.formatMessage() pour formater le message et le stocker
// TODO: Créer un EmailMessenger avec le destinataire de l'e-mail
// TODO: Créer un SMSMessenger avec le numéro de téléphone
// TODO: Appeler sendWithTimestamp() sur le EmailMessenger avec le message formaté
// TODO: Appeler sendWithTimestamp() sur le SMSMessenger avec le message formaté
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesChamps (Attributs)Méthode constructeurSurcharge de constructeurRécapitulatif - Calculatrice simple4Héritage
Héritage de base (extends)Le mot-clé superRedéfinition de méthode (@Override)Chaînage de constructeursLa classe ObjectHéritage simple et multiniveauPourquoi pas d'héritage multiple de classesRécapitulatif - Hiérarchie des employés7Méthodes spéciales et classe Object
Méthode toString()equals() et hashCode()Méthode clone()compareTo() et ComparableInterface ComparatorRécapitulatif - Tri personnalisé2Modificateurs d'accès et Encapsulation
Aperçu des niveaux d'accèsMéthodes Getter et SetterMasquage d'informationsLe mot-clé finalRécapitulatif - Gestionnaire de compte bancaire5Polymorphisme
Bases de la surcharge de méthodesRedéfinition de méthodes (Run-Time)Upcasting et DowncastingL'opérateur instanceofClasses et méthodes abstraitesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageAgrégation vs CompositionClasses internes, imbriquées et anonymesEnums et méthodes d'EnumRecords (Java 16+)Classes scellées (Java 17+)11Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron MonteurPatron ObservateurPatron Stratégie3Propriétés de classe et membres statiques
Variables d'instance vs variables statiquesMéthodes statiquesBlocs statiquesConstantes (static final)Récapitulatif - Compteur et utilitaire6Interfaces et Classes Abstraites
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesDefault et Static dans les InterfacesClasses Abstraites vs InterfacesInterfaces FonctionnellesRécapitulatif - Système de Paiement9La généricité
Introduction à la généricitéClasses génériquesMéthodes génériquesParamètres de type bornésWildcards (?, extends, super)Récapitulatif - Conteneur générique12Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositePatron Itérateur