Keyboard shortcuts

Touchez ← ou → pour naviguer les chapitres

Touchez S ou / pour chercher dans le livre

Touchez ? pour afficher ce message

Touchez Esc pour masquer ce message

Accueil > Classes et objets >

📚 MĂ©thodes typiques d’une classe Java

Survol et attentes

Toutes les classes Java hĂ©ritent automatiquement tout ce qui est dĂ©fini dans la classe Object, mĂȘme les classes que vous Ă©crivez. Cette classe contient plusieurs mĂ©thodes utiles que les dĂ©veloppeurs tendent Ă  réécrire, ce qu’on appelle supplanter une mĂ©thode, pour les adapter aux nouveaux objets.

Définitions
Surcharger une méthode
DĂ©finir plusieurs fois une mĂ©thode avec le mĂȘme nom mais avec des paramĂštres diffĂ©rents. Java choisit la version de la mĂ©thode Ă  appeler en fonction des paramĂštres passĂ©s Ă  la mĂ©thode.
Supplanter une méthode
RedĂ©finir une mĂ©thode dĂ©jĂ  dĂ©finie dans une classe parente, souvent dans la classe Object (parent de toutes les classes Java). On utilise le dĂ©corateur @Override pour signaler explicitement qu’on tente de supplanter une mĂ©thode dĂ©jĂ  dĂ©finie. Des synonymes pour “supplanter” sont “remplacer” ou “surclasser”.
Constructeur
MĂ©thode spĂ©ciale qui initialise les objets d’une maniĂšre spĂ©cifique. Le nom d’un constructeur est le mĂȘme que le nom de la classe. C’est commun de surcharger le constructeur : un constructeur par dĂ©faut (sans paramĂštres) qui appelle le constructeur plus gĂ©nĂ©ral en lui passant des valeurs par dĂ©faut comme arguments. On utilise l’appel this([paramĂštres]) pour Ă©viter de dupliquer le code Ă©crit dans le constructeur plus gĂ©nĂ©ral.
Méthode String toString()
MĂ©thode qui produit une reprĂ©sentation textuelle de l’objet. Cette mĂ©thode est appellĂ© automatiquement quand on tente d’afficher un objet, mais la dĂ©finition par dĂ©faut (dans Object) affiche le nom de la classe suivi par un code hexadĂ©cimal. Il est souvent prĂ©fĂ©rable de supplanter cette mĂ©thode pour afficher des informations plus utiles.
Méthodes boolean equals(Object) et int hashCode()
La mĂ©thode equals compare le contenu de deux objets pour dĂ©terminer s’ils sont Ă©gaux. La mĂ©thode hashCode retourne un entier qui identifie l’objet. La classe Object spĂ©cifie un contrat entre ces deux mĂ©thodes : si deux objets retournent vrai avec equals, ils doivent aussi retourner le mĂȘme entier avec hashCode. Il est donc important de supplanter ces deux mĂ©thodes ensemble. Les EDI modernes peuvent gĂ©nĂ©rer ces mĂ©thodes automatiquement pour vous.

Objectifs d’apprentissage

À la fin de cette leçon vous devrez ĂȘtre en mesure de :

  • DĂ©crire le rĂŽle d’un constructeur et de la mĂ©thode toString.
  • Expliquer pourquoi il faut dĂ©finir les mĂ©thodes hashCode et equals ensemble.
  • DĂ©finir et distinguer surcharger une mĂ©thode et supplanter une mĂ©thode.

CritĂšres de succĂšs

  • Je suis capable de surcharger des constructeurs sans dupliquer le code, notamment en utilisant l’appel this().
  • Je peux produire un toString qui affiche des informations utiles sur mes objets.
  • Je suis capable de gĂ©nĂ©rer les mĂ©thodes hashCode et equals dans mes propres objets avec l’aide de l’EDI.

Constructeurs

On dĂ©finit une mĂ©thode spĂ©ciale qui s’appelle un constructeur afin d’initialiser les objets d’une maniĂšre spĂ©cifique. La signature du constructeur est simplement le nom de la classe suivi par des parenthĂšses, avec ou sans paramĂštres.

class ShinyObject {
    boolean isShiny;

    /** Constructeur */
    ShinyObject() {
        isShiny = true; // initialise avec une valeur littérale
    }
}

Les constructeurs sont gĂ©nĂ©ralement surchargĂ©s, c’est-Ă -dire dĂ©finis plusieurs fois avec diffĂ©rents paramĂštres. On dĂ©finit souvent une version sans paramĂštres et une version avec un paramĂštre par attribut afin d’initialiser chaque attribut dĂšs la crĂ©ation d’une instance de l’objet.

Pour Ă©viter de dupliquer le code dans les constructeurs, c’est une bonne pratique d’appeler le constructeur le plus complet dans les autres constructeurs. On le fait avec la mĂ©thode this([paramĂštres,...]).

class ShinyObject {
    boolean isShiny;

    /** Constructer avec paramĂštre */
    ShinyObject(boolean isShiny) {
        this.isShiny = isShiny; // initialise avec le paramĂštre
    }

    /** Constructeur sans paramĂštres */
    ShinyObject() {
        this(true); // passe la valeur par défaut comme argument
    }
}

Le constructueur par défaut (définit dans la classe Object) est un constructeur sans paramÚtres qui assigne la valeur par défaut aux attributs :

  • 0 pour les nombres,
  • '' pour les char,
  • false pour les boolean et
  • null pour les objets, comme les String.

Méthode String toString()

La mĂ©thode toString produit une reprĂ©sentation textuelle de l’objet, normalement en affichant de maniĂšre conviviale les valeurs des attributs. La dĂ©finition par dĂ©faut affiche le nom de la classe suivi par un code hexadĂ©cimal.

ShinyObject@2c7b84de

C’est dĂ©finitivement mieux de supplanter (remplacer, surclasser) cette dĂ©finition!

Reprenant la classe ShinyObject ci-dessus, on pourrait lui ajouter la méthode toString suivante :

@Override
public String toString(){
    String validationTxt = isShiny ? "est" : "n'est pas"; // opérateur ternaire = if-else compact
    return String.format("Cet objet %S reluisant", validationTxt);
}

Notez que la mĂ©thode retourne un String mais ne l’affiche pas (pas de System.out.println() ni de IO.println()).

Notez aussi qu’on prĂ©cĂšde la signature de la mĂ©thode avec le dĂ©corateur @Override afin de signaler plus explicitement qu’on tente de supplanter une mĂ©thode dĂ©jĂ  dĂ©finie dans la classe Object. Le dĂ©corateur est optionnel mais force le compilateur Ă  vĂ©rifier que vous avez bien redĂ©finie une mĂ©thode existante, p. ex.: vous n’avez pas tapez tostring par accident ou mĂ©garde au lieu de toString.

Pour les valeurs dĂ©cimales, c’est souvent une bonne idĂ©e d’utiliser un texte formatĂ© pour limiter le nombre de places aprĂšs la virgule Ă  une prĂ©cision spĂ©cifique. Prenons l’exemple suivant :

class Student {
    String name;
    double average;

    @Override
    public String toString() {
        return String.format("%s a une moyenne de %.2f", name, average);
    }
}

On remarque plusieurs choses ici :

  • On utilise la mĂ©thode String String.format(String, [valeurs]) pour produire le texte et non la concatĂ©nation de texte et de valeurs.
  • Le String intĂšgre des spĂ©cifications de format directement dans le texte - le %s et le %0.2f. Ces spĂ©cifications font trois choses :
    • la lettre Ă  la fin correspond Ă  un type de donnĂ©es : s ou S pour les String, d pour les int, f pour les double ou float, etc.
    • les caractĂšres entre le % et la lettre donne un format optionnel. Dans le cas du %.2f, le .2 signale d’afficher seulement deux places aprĂšs la virgule.
    • la prĂ©sence de chaque spĂ©cification dĂ©termine combien et quels types de valeurs doivent suivre le String dans la mĂ©thode : il faut une valeur du bon type pour chaque spĂ©cification de format. Ces valeurs doivent suivre dans le mĂȘme ordre que l’ordre d’apparence des spĂ©cifications dans le String.

Pour plus de détails sur les spécifications et options de format possibles, voir la documentation pour la classe Formatter.

Méthodes boolean equals(Object) et int hashCode()

La comparaison == donne vrai si les deux objets occupent le mĂȘme bloc en mĂ©moire. Ça marche pour les valeurs primitives (int, double, char, etc.) parce que chaque nouvelle valeur primitive possible prend une nouvelle place en mĂ©moire.

Pour les objets, par contre, chaque instance occupe une nouvelle place en mĂ©moire, peu importe si les valeurs des attributs sont identiques. C’est pourquoi on utilise la mĂ©thode equals pour comparer le texte de deux Strings. En fait, il faut utiliser cette mĂ©thode pour comparer le contenu de tous les types d’objets, pas juste les String.

La classe Object spĂ©cifie un contrat entre la mĂ©thode equals et une autre mĂ©thode, hashCode : il faut que deux instances qui retournent vrai avec le mĂ©thode equals retournent aussi le mĂȘme int avec la mĂ©thode hashCode. Ça devient donc important de dĂ©finir les deux mĂ©thodes ensemble.

Voici un exemple (attachez vos tuques!) :

class Student {
    String name;
    double average;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        long temp;
        temp = Double.doubleToLongBits(average);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        // clauses de garde
        if (this == obj) // l'autre pointe au mĂȘme bloc de mĂ©moire
            return true;
        if (obj == null) // l'autre pointe Ă  rien
            return false;
        if (getClass() != obj.getClass()) // l'autre n'est pas du mĂȘme type
            return false;

        // créer une instance du bon type avec l'autre Object
        Square other = (Square) obj;
        // comparaison des attributs des objets
        if (Double.doubleToLongBits(average) != Double.doubleToLongBits(other.average))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

PremiĂšre chose Ă  dire : ces deux mĂ©thodes ont Ă©tĂ© gĂ©nĂ©rĂ©es automatiquement par l’EDI VS Code. D’autres EDI, comme Eclipse et IntelliJ, font ça aussi. C’est la façon la plus simple de les produire, surtout que c’est seulement la section “Comparaison des attributs des objets” dans la mĂ©thode equals qui pourrait (peut-ĂȘtre) nĂ©cessiter un ajustement si vous aviez envi de faire une comparaison particuliĂšre. Le reste dans equals et dans hashCode doit ĂȘtre lĂ . Et, dans ce cours, ce n’est pas nĂ©cessaire de comprendre tous les dĂ©tails.

Alors voici comment gĂ©nĂ©rer ces mĂ©thodes automatiquement avec VS Code (avec le “Extension Pack for Java” dĂ©veloppĂ© par Microsoft, vscjava.vscode-java-pack) :

  1. Cliquez sur le nom de la classe dans sa signature.
  2. Ici vous avez deux choix :
    1. Faites un clic droit sur le nom et cliquez ensuite sur l’option “Source Action
”
    2. Faites la combinaison Ctrl + . et consultez la section “More Actions”
  3. Cliquez sur “Generate hashCode() and equals()
”
  4. SĂ©lectionnez les attributs Ă  inclure dans leurs algorithmes et cliquez “OK”.
  5. Validez le code en faisant quelque tests avec différentes instances via la classe pilote ou une classe test.
  6. Optionnellement, ajustez le code dans equals() si vous avez une autre comparaison que vous préférez implémenter. Refaire les tests aprÚs toute modification.

Exercices

📚 Tester la comprĂ©hension

Quiz de vĂ©rification sur les mĂ©thodes typiques d’Objects Java

đŸ› ïž Pratique

Écrivez deux constructeurs pour votre objet, un sans paramĂštres qui utilise l’appel this([paramĂštres]) pour appeler le deuxiĂšme qui est dĂ©fini avec les paramĂštres nĂ©cessaires pour initialiser les attributs de l’objet.

Supplanter les méthodes hashCode, equals et toString pour votre objet.

Testez ces nouvelles méthodes dans la classe pilote.

© 2022-2025 David Crowley