Menu
Coddy logo textTech

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 Circle

Les 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.

challenge icon

Défi

Facile

Construisons 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 champ brand (String) et un champ wattage (int). Incluez un constructeur qui initialise les deux champs, des méthodes getter pour chacun, et une méthode régulière getInfo() qui retourne : [brand] - [wattage]W. Définissez une méthode abstraite operate() 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émentaire capacity (int) représentant la taille de la charge en kg. Utilisez super pour gérer l'initialisation du parent. Implémentez la méthode operate() pour afficher : [brand] washing machine is washing [capacity]kg of clothes
  • Microwave.java : Créez une autre classe concrète qui étend Appliance. Les micro-ondes ont un champ power (int) représentant le pourcentage du niveau de puissance. Implémentez operate() pour afficher : [brand] microwave is heating at [power]% power
  • Main.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érences Appliance. Parcourez le tableau et, pour chaque appareil, affichez ses informations à l'aide de getInfo() 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 Circle

Les 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()
    }
}
quiz iconTestez-vous

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