Classes et méthodes abstraites
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 32 sur 87.
Parfois, vous souhaitez définir une classe qui sert de modèle mais qui ne devrait jamais être instanciée directement. Par exemple, une classe Shape générique est logique en tant que parent, mais à quoi ressemblerait une « forme » sans forme spécifique ? C'est là que les classes abstraites entrent en jeu.
Une classe abstraite est déclarée avec le mot-clé abstract et ne peut pas être instanciée. Elle peut contenir à la fois des méthodes régulières avec des implémentations et des méthodes abstraites qui n'ont pas de corps :
public abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
// Méthode abstraite - pas d'implémentation
public abstract double getArea();
// Méthode régulière - a une implémentation
public String getColor() {
return color;
}
}Les méthodes abstraites déclarent ce qu'une sous-classe doit faire, mais pas comment. Toute classe non abstraite étendant une classe abstraite doit fournir des implémentations pour toutes les méthodes abstraites :
public class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}Vous pouvez toujours utiliser les classes abstraites comme types de référence, permettant le polymorphisme :
Shape shape = new Circle("red", 5.0);
System.out.println(shape.getArea()); // Appelle l'implémentation de CircleLes classes abstraites sont idéales lorsque les sous-classes partagent du code commun mais doivent chacune implémenter certains comportements différemment. Elles imposent un contrat tout en permettant la réutilisation du code.
Défi
FacileConstruisons un système d'appareils électroménagers qui démontre la puissance des classes abstraites. Vous allez créer une classe de base Appliance qui définit ce que chaque appareil doit faire, tout en laissant les types d'appareils spécifiques décider exactement comment ils le font.
Vous organiserez votre code sur quatre fichiers :
Appliance.java: Créez une classe abstraite qui sert de modèle pour tous les appareils. Chaque appareil possède un champbrand(String) et un champwattage(int). Incluez un constructeur qui initialise les deux champs, des méthodes getter pour chacun, et une méthode régulièregetInfo()qui retourne :[brand] - [wattage]W. Définissez une méthode abstraiteoperate()que les sous-classes doivent implémenter - cela représente la manière dont chaque appareil remplit sa fonction principale.WashingMachine.java: Créez une classe concrète qui étend Appliance. Les machines à laver ont un champ supplémentairecapacity(int) représentant la taille de la charge en kg. Utilisezsuperpour gérer l'initialisation du parent. Implémentez la méthodeoperate()pour afficher :[brand] washing machine is washing [capacity]kg of clothesMicrowave.java: Créez une autre classe concrète qui étend Appliance. Les micro-ondes ont un champpower(int) représentant le pourcentage du niveau de puissance. Implémentezoperate()pour afficher :[brand] microwave is heating at [power]% powerMain.java: Rassemblez le tout en utilisant le polymorphisme. Vous recevrez cinq entrées : un nom de marque, une puissance en watts, une capacité de machine à laver, un autre nom de marque et un niveau de puissance de micro-ondes. Créez une WashingMachine et un Microwave, puis stockez-les dans un tableau de référencesAppliance. Parcourez le tableau et, pour chaque appareil, affichez ses informations à l'aide degetInfo()suivi de l'appel àoperate().
Vous recevrez cinq entrées dans cet ordre : première marque (String), première puissance (int), capacité en kg (int), deuxième marque (String) et niveau de puissance (int).
Votre sortie devrait afficher quatre lignes - pour chaque appareil, vous verrez sa ligne d'information suivie de son comportement de fonctionnement. Remarquez comment la classe abstraite vous permet de traiter différents appareils de manière uniforme alors que chacun fonctionne de sa propre manière unique !
Aide-mémoire
Une classe abstraite est déclarée avec le mot-clé abstract et ne peut pas être instanciée directement. Elle sert de modèle pour les sous-classes :
public abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
// Méthode abstraite - pas d'implémentation
public abstract double getArea();
// Méthode régulière - possède une implémentation
public String getColor() {
return color;
}
}Les méthodes abstraites n'ont pas de corps et doivent être implémentées par les sous-classes non abstraites :
public class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}Les classes abstraites peuvent être utilisées comme types de référence pour le polymorphisme :
Shape shape = new Circle("red", 5.0);
System.out.println(shape.getArea()); // Appelle l'implémentation de CircleLes classes abstraites sont idéales lorsque les sous-classes partagent du code commun mais doivent implémenter certains comportements différemment.
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 brand1 = scanner.nextLine();
int wattage1 = scanner.nextInt();
int capacity = scanner.nextInt();
scanner.nextLine(); // consommer le saut de ligne
String brand2 = scanner.nextLine();
int power = scanner.nextInt();
// TODO: Créer un objet WashingMachine avec brand1, wattage1, et capacity
// TODO: Créer un objet Microwave avec brand2, wattage1 (ou la puissance appropriée), et power
// TODO: Créer un tableau de références Appliance et stocker les deux objets
// TODO: Parcourir le tableau et pour chaque appliance :
// - Afficher ses informations en utilisant getInfo()
// - Appeler operate()
}
}
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