Menu
Coddy logo textTech

Classes internes, imbriquées et anonymes

Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy. Leçon 49 sur 87.

Java vous permet de définir des classes à l'intérieur d'autres classes. Ces classes internes aident à organiser le code en regroupant les fonctionnalités liées et peuvent accéder directement aux membres de la classe externe.

Une classe interne imbriquée est définie comme un membre d'une autre classe. Elle a accès à tous les champs et méthodes de la classe externe, y compris les membres privés :

class Outer {
    private String message = "Hello";
    
    class Inner {
        void display() {
            System.out.println(message);  // Peut accéder au champ privé
        }
    }
}

// Utilisation
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display();  // Affiche : Hello

Une classe interne locale est définie à l'intérieur d'une méthode. Elle ne peut être utilisée qu'au sein de cette méthode et peut accéder aux variables locales qui sont effectivement finales :

void process() {
    String prefix = "Result: ";
    
    class LocalHelper {
        void print(int value) {
            System.out.println(prefix + value);
        }
    }
    
    new LocalHelper().print(42);
}

Une classe interne anonyme est une classe sans nom, créée et instanciée en une seule expression. Elle est couramment utilisée pour implémenter des interfaces ou étendre des classes à la volée :

Comparator<String> comp = new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return a.length() - b.length();
    }
};

Les classes internes sont particulièrement utiles lorsqu'une classe n'est pertinente que pour une seule autre classe, ce qui permet de garder votre code organisé et encapsulé.

challenge icon

Défi

Facile

Construisons un système de panier d'achat qui présente les trois types de classes internes. Vous créerez un ShoppingCart qui utilise une classe interne imbriquée pour représenter les articles, une classe interne locale pour calculer les réductions et une classe interne anonyme pour formater le reçu final.

Vous organiserez votre code sur deux fichiers :

  • ShoppingCart.java : créez la classe externe qui gère une expérience d'achat. Votre ShoppingCart doit posséder un champ privé customerName (String).

    Dans ShoppingCart, définissez une classe interne imbriquée appelée Item avec deux champs privés : name (String) et price (double). Donnez à Item un constructeur pour initialiser les deux champs ainsi qu'une méthode getDetails() qui renvoie : [name]: $[price]

    Votre ShoppingCart a besoin d'un constructeur qui accepte le nom du client, ainsi que d'une méthode appelée checkout() qui accepte un Item et un pourcentage de réduction (double). Dans checkout() :

    1. Créez une classe interne locale appelée DiscountCalculator avec une méthode applyDiscount(double originalPrice) qui renvoie le prix après application du pourcentage de réduction.
    2. Utilisez la classe locale pour calculer le prix final.
    3. Créez une classe interne anonyme qui implémente l'interface Formatter (vous allez définir cette interface) afin de formater le reçu. La classe anonyme doit redéfinir une méthode format() qui renvoie une chaîne de caractères représentant un reçu sur plusieurs lignes.

    La méthode checkout() doit renvoyer la chaîne du reçu formatée selon ce format exact :

    --- Receipt ---
    Customer: [customerName]
    Item: [item details from getDetails()]
    Discount: [discount]%
    Final Price: $[calculated price]
  • Formatter.java : définissez une interface simple avec une seule méthode : String format(). Cette interface sera implémentée par votre classe interne anonyme dans la méthode checkout.
  • Main.java : donnez vie à votre panier d'achat ! Vous recevrez trois entrées : le nom du client (String), le nom de l'article (String) et le prix de l'article (double). Le pourcentage de réduction est fixé à 10.0.

    Créez un ShoppingCart avec le nom du client. Créez ensuite un Item en utilisant la syntaxe de référence de la classe externe : cart.new Item(name, price). Appelez checkout() avec l'article et la réduction, puis affichez le reçu renvoyé.

Vous recevrez trois entrées dans l'ordre suivant : le nom du client, le nom de l'article et le prix de l'article.

Par exemple, si les entrées sont Alice, Laptop et 1000.0, le prix final après une réduction de 10 % serait 900.0.

Remarquez comment chaque type de classe interne sert un objectif différent : la classe imbriquée regroupe les données associées à la classe externe, la classe locale encapsule la logique nécessaire uniquement au sein d'une méthode et la classe anonyme fournit une implémentation rapide et unique d'une interface !

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 customerName = scanner.nextLine();
        String itemName = scanner.nextLine();
        double itemPrice = scanner.nextDouble();
        
        double discount = 10.0;
        
        // TODO: Créer un ShoppingCart avec le nom du client
        
        // TODO: Créer un Item en utilisant : cart.new Item(itemName, itemPrice)
        
        // TODO: Appeler checkout() avec le item et le discount, puis afficher le résultat
        
    }
}
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

Entraînez-vous par vous-même : Compilateur Java en ligne