CodeGym /Cours /JAVA 25 SELF /Record avec des méthodes

Record avec des méthodes

JAVA 25 SELF
Niveau 22, Leçon 3
Disponible

1. Extension d’un record : méthodes supplémentaires

Peut-on ajouter des méthodes à un record ?

Bien sûr ! Un Record, c’est comme un appartement déjà rénové : les murs et le sol sont faits, on ne peut pas les changer, mais personne ne vous interdit d’y disposer les meubles à votre façon. À l’intérieur d’un record, on peut déclarer des méthodes ordinaires, des méthodes statiques et même conserver des constantes. Cela signifie que la logique métier n’a pas forcément besoin d’être déplacée dans des classes « utilitaires » — on peut l’intégrer proprement directement dans le record lui‑même.

Exemple : méthode de calcul de la distance entre deux points

Supposons que nous ayons un record pour un point dans le plan :


public record Point(int x, int y) {
    // Méthode supplémentaire
    public double distanceTo(Point other) {
        int dx = this.x - other.x;
        int dy = this.y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}

On peut désormais faire ceci :


Point p1 = new Point(0, 0);
Point p2 = new Point(3, 4);
System.out.println(p1.distanceTo(p2)); // 5.0

Comme vous le voyez, on peut « enrichir » un record avec ses propres méthodes — et c’est très pratique !

Exemple : méthode statique


public record Rectangle(int width, int height) {
    public int area() {
        return width * height;
    }

    public static Rectangle square(int size) {
        return new Rectangle(size, size);
    }
}

On peut maintenant créer un « carré » en un seul appel :


Rectangle r = Rectangle.square(5);
System.out.println(r.area()); // 25

2. Constructeur compact et validation des données

À quoi sert le constructeur « compact » ?

Le constructeur canonique d’un record est créé automatiquement et assigne les paramètres aux champs. Mais parfois, on souhaite ajouter une vérification des données d’entrée (par exemple, interdire des coordonnées négatives).

Dans une classe ordinaire, nous écririons :


public class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        if (x < 0 || y < 0) throw new IllegalArgumentException();
        this.x = x;
        this.y = y;
    }
    // ...
}

Dans un record, on peut déclarer un constructeur compact — sans répéter la liste des paramètres et sans affectation explicite des champs (le compilateur s’en charge).

Syntaxe du constructeur compact


public record Point(int x, int y) {
    public Point {
        if (x < 0 || y < 0) {
            throw new IllegalArgumentException("Coordinates must be non-negative");
        }
        // Inutile d’écrire : this.x = x; this.y = y;
    }
}
  • Les paramètres du constructeur correspondent automatiquement aux composants du record.
  • L’affectation this.x = x et this.y = y est effectuée par le compilateur automatiquement après l’exécution du corps du constructeur (ou après en être sorti avec succès).
  • Si une exception est levée, l’objet ne sera pas créé.

Exemple avec validation


Point p1 = new Point(3, 5); // OK
Point p2 = new Point(-1, 2); // Lève IllegalArgumentException !

Peut-on déclarer un « constructeur classique » ?

Oui ! Si vous devez créer un constructeur avec une autre liste de paramètres ou une logique supplémentaire, déclarez‑le explicitement :


public record Range(int from, int to) {
    public Range(int size) {
        this(0, size); // appelle le constructeur principal
    }
}

3. Limitations des records

Contrairement aux classes ordinaires, les record ont un certain nombre de limitations. C’est important à garder en tête pour éviter de s’étonner des erreurs de compilation.

Uniquement des composants — aucun champ d’instance supplémentaire

Dans un record, il est interdit de déclarer de nouveaux champs d’instance :


public record Person(String name, int age) {
    // int id; // Erreur de compilation ! Impossible d’ajouter des champs d’instance.
}

On peut déclarer des champs et des méthodes statiques :


public record Person(String name, int age) {
    public static final String SPECIES = "Homo sapiens";
}

Un record est toujours final

Un record ne peut pas être une superclasse (on ne peut pas en hériter) et ne peut pas lui‑même hériter explicitement d’une autre classe (à part l’héritage implicite de java.lang.Record). Autrement dit, un record est toujours une structure « finale ».


public record User(String login) { }

// public class Admin extends User {} // Erreur : impossible d’hériter d’un record !

On peut implémenter des interfaces

Un Record peut implémenter des interfaces :


public interface Printable {
    void print();
}

public record Invoice(int amount) implements Printable {
    @Override
    public void print() {
        System.out.println("Montant : " + amount);
    }
}

4. Exemples : records avancés dans des cas concrets

Voyons quelques exemples pratiques où des méthodes supplémentaires et des constructeurs compacts rendent un record vraiment utile.

Record avec méthode de calcul


public record Circle(double x, double y, double radius) {
    public double area() {
        return Math.PI * radius * radius;
    }

    public double distanceTo(Circle other) {
        double dx = x - other.x;
        double dy = y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}

Record avec validation


public record Email(String value) {
    public Email {
        if (value == null || !value.contains("@")) {
            throw new IllegalArgumentException("Adresse e-mail invalide : " + value);
        }
    }
}

On ne peut plus créer un e‑mail invalide :


Email e1 = new Email("test@example.com"); // OK
Email e2 = new Email("not-an-email"); // Lève IllegalArgumentException

Record avec méthodes statiques supplémentaires


public record Temperature(double celsius) {
    public static Temperature fromFahrenheit(double fahrenheit) {
        return new Temperature((fahrenheit - 32) * 5 / 9);
    }

    public double toFahrenheit() {
        return celsius * 9 / 5 + 32;
    }
}

Utilisation :


Temperature t = Temperature.fromFahrenheit(98.6);
System.out.println(t.celsius()); // 37.0
System.out.println(t.toFahrenheit()); // 98.6

5. Constructeur compact : nuances et limitations

Quand utiliser un constructeur compact ?

  • Si vous devez vérifier la validité des données (validation).
  • Si vous devez modifier des valeurs avant de les conserver (par exemple, arrondir un nombre ou mettre une chaîne en majuscules).
  • Si vous souhaitez éviter de dupliquer la liste des paramètres.

Particularités

  • Dans un constructeur compact, on ne peut pas affecter explicitement des valeurs aux composants (this.x = ...) — cela provoquera une erreur de compilation, car le compilateur effectue lui‑même l’affectation après l’exécution du corps du constructeur.
  • Dans un constructeur compact, on ne peut pas changer les noms des paramètres — ils correspondent toujours aux noms des composants du record.

Exemple : arrondi automatique


public record Money(double amount) {
    public Money {
        amount = Math.round(amount * 100) / 100.0; // Arrondir aux centimes
    }
}

6. Pratique : faire évoluer une application pédagogique

Supposons que nous implémentions des opérations bancaires dans une application pédagogique. Disons que nous avons un record Transaction qui stocke le montant, l’émetteur et le bénéficiaire.


public record Transaction(String from, String to, double amount) {
    public Transaction {
        if (amount <= 0) throw new IllegalArgumentException("Le montant doit être positif");
        if (from == null || to == null) throw new IllegalArgumentException("Les champs ne peuvent pas être null");
    }

    public String description() {
        return String.format("Virement %.2f de %s à %s", amount, from, to);
    }
}

Utilisation :


Transaction t = new Transaction("Alice", "Bob", 150.0);
System.out.println(t.description()); // Virement 150.00 de Alice à Bob

Toute tentative de créer une transaction invalide provoquera une erreur :


Transaction t2 = new Transaction("Alice", "Bob", -10.0); // IllegalArgumentException

Tableau : ce qui est possible et ce qui est interdit dans un record

Permis dans un record Interdit dans un record
Méthodes d’instance Nouveaux champs d’instance
Méthodes et champs statiques Hériter d’autres classes
Implémenter des interfaces Être la superclasse d’autres classes
Constructeurs compacts et classiques Modifier les composants après création
Redéfinir des méthodes Utiliser des setters

7. Erreurs typiques lors de l’utilisation de records avec un corps non standard

Erreur n° 1 : tentative d’ajouter un champ d’instance.
Les débutants essaient souvent d’ajouter à un record « un champ de plus pour la logique interne » — par exemple, un compteur ou un cache. Cela ne fonctionne pas : le compilateur lève immédiatement une erreur. Si vous devez conserver un état supplémentaire, il est probable qu’un record ne soit pas le bon choix.

Erreur n° 2 : oublier la validation dans le constructeur compact.
Si vous souhaitez que l’objet soit toujours valide, effectuez les vérifications dans le constructeur compact. Ne comptez pas sur le fait que « l’utilisateur n’entrera pas de bêtises ».

Erreur n° 3 : tentative de modifier un composant après création.
Les champs d’un record sont final — on ne peut pas les modifier, ni directement, ni via des méthodes. Si vous avez besoin d’une structure mutable, utilisez une classe ordinaire.

Erreur n° 4 : duplication de la logique dans les méthodes et le constructeur.
Parfois, on duplique la logique de vérification et la logique de calcul à la fois dans les méthodes et dans le constructeur. Il vaut mieux effectuer toute la validation dans le constructeur et réserver les méthodes à la « pure » logique métier.

Erreur n° 5 : oublier les limitations d’héritage.
Un Record est toujours final — on ne peut pas en créer un sous‑type. Si vous concevez une hiérarchie qui nécessite des sous‑classes, utilisez des classes ordinaires.

1
Mission
JAVA 25 SELF, niveau 22, leçon 3
Bloqué
Lectures du thermomètre à la station météorologique 🌡️
Lectures du thermomètre à la station météorologique 🌡️
1
Mission
JAVA 25 SELF, niveau 22, leçon 3
Bloqué
Validation de l'adresse e-mail lors de l'inscription 📧
Validation de l'adresse e-mail lors de l'inscription 📧
1
Mission
JAVA 25 SELF, niveau 22, leçon 3
Bloqué
Création d'une fiche de personnage avec données communes 🧍
Création d'une fiche de personnage avec données communes 🧍
1
Mission
JAVA 25 SELF, niveau 22, leçon 3
Bloqué
Enregistrement des transactions financières à la banque 💸
Enregistrement des transactions financières à la banque 💸
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION