CodeGym /Cours /JAVA 25 SELF /Utilisation de super : appel du constructeur et des métho...

Utilisation de super : appel du constructeur et des méthodes de la classe de base

JAVA 25 SELF
Niveau 17 , Leçon 2
Disponible

1. Utiliser super pour appeler les méthodes de la classe de base

Lorsque vous créez une sous-classe, il arrive parfois que vous deviez accéder aux champs ou aux méthodes de la classe de base, en particulier si vous les avez remplacés (overrides) ou « masqués » dans la sous-classe. Pour cela, Java fournit un mot-clé spécial — super.

Par analogie, super, c’est comme « maman, à l’aide ! » lorsque, depuis une sous-classe, vous voulez explicitement accéder à ce qui est défini dans le parent.

Imaginez que vous avez une classe Animal avec une méthode eat() qui affiche simplement "L'animal mange". Et dans la classe Cat, vous souhaitez que le chat fasse d’abord quelque chose à lui (par exemple, miauler), puis exécute quand même le « L’animal mange » standard. C’est là que super.eat() est utile.

Lorsque, dans une sous-classe, vous redéfinissez une méthode mais que vous voulez quand même appeler à l’intérieur l’implémentation de cette méthode de la classe de base, utilisez super.nomDeMethode().

Exemple : étendre le comportement

class Animal {
    void eat() {
        System.out.println("L'animal mange");
    }
}

class Cat extends Animal {
    @Override
    void eat() {
        System.out.println("Le chat renifle la nourriture...");
        super.eat(); // on appelle la méthode eat() d'Animal
        System.out.println("Le chat ronronne, satisfait");
    }
}

Comment cela fonctionne-t-il ?

  • Lorsque eat() est appelé sur un objet de type Cat, le code de Cat.eat() s’exécute d’abord, c’est-à-dire la méthode propre au chat.
  • À l’intérieur de cette méthode, nous appelons explicitement super.eat(), c’est-à-dire l’implémentation de la classe parente Animal.
  • Cela permet d’ajouter un comportement supplémentaire sans oublier celui du « parent ».

Pratique : utilisation dans une application

Supposons que, dans notre application d’apprentissage, il y ait une classe de base Animal et des sous-classes Dog et Cat. Nous voulons qu’au moment de nourrir un animal, les actions communes (par exemple, augmenter la satiété) soient exécutées, ainsi que les actions spécifiques à chaque animal.

class Animal {
    int satiety = 0;

    void eat() {
        satiety += 10;
        System.out.println("L'animal mange. Satiété : " + satiety);
    }
}

class Dog extends Animal {
    @Override
    void eat() {
        System.out.println("Le chien remue la queue avant de manger");
        super.eat();
    }
}

Désormais, si vous appelez dog.eat(), vous verrez les deux messages, et satiety augmentera correctement.

2. Utiliser super pour accéder aux champs de la classe de base

Si, dans une sous-classe, vous déclarez un champ portant le même nom que dans la classe parente, il « masque » le champ du parent. Parfois, vous devez accéder au champ original de la classe de base — pour cela, utilisez super.nomDuChamp.

Exemple : masquage d’un champ

class Animal {
    String name = "Animal";
}

class Cat extends Animal {
    String name = "Chat";

    void printNames() {
        System.out.println("Nom depuis Cat : " + name);
        System.out.println("Nom depuis Animal : " + super.name);
    }
}

L’appel new Cat().printNames(); affichera :

Nom depuis Cat : Chat
Nom depuis Animal : Animal

En pratique, il est déconseillé de « masquer » les champs sans nécessité absolue, mais il est utile de connaître cette possibilité.

3. Appeler le constructeur de la classe de base via super(...)

Comment les objets sont-ils créés dans une hiérarchie ?

Lorsque vous créez un objet d’une sous-classe, le constructeur de la classe de base est appelé en premier, puis celui de la sous-classe. Cela permet d’initialiser correctement tous les champs, puisque la sous-classe « hérite » d’une partie de l’état du parent.

Appel explicite du constructeur de la classe de base

Si la classe de base possède un constructeur sans paramètre, c’est simple : Java l’appellera elle-même avant d’exécuter le constructeur de la sous-classe. Mais si le parent n’a pas de constructeur sans paramètre, vous devez explicitement appeler le constructeur voulu via super(...).

Exemple :

class Animal {
    String name;

    Animal(String name) {
        this.name = name;
        System.out.println("Animal créé : " + name);
    }
}

class Cat extends Animal {
    Cat(String name) {
        super(name); // obligatoire ! Pas de constructeur Animal() sans paramètre
        System.out.println("Chat créé : " + name);
    }
}

L’appel new Cat("Murka") affichera :

Animal créé : Murka
Chat créé : Murka

Important : l’appel au constructeur parent via super(...) doit être la première ligne du constructeur de la sous-classe. Si vous écrivez quelque chose avant cet appel, le compilateur ne sera pas content et vous le rappellera.

Et si on ne l’appelle pas explicitement ?
Si le parent n’a qu’un constructeur avec paramètres et que vous ne l’appelez pas explicitement via super(...), le compilateur générera une erreur : "constructor Animal in class Animal cannot be applied to given types".

4. Points utiles

Quand utiliser super ?

Pour étendre, pas remplacer le comportement.
Parfois, vous ne voulez pas complètement remplacer le comportement d’une méthode, mais seulement l’« étendre ». Par exemple, ajouter quelque chose avant ou après la logique parente. Dans ce cas, utilisez super.nomDeMethode() dans le corps de la méthode redéfinie.

Pour initialiser les champs hérités.
Si le parent possède des champs obligatoires à initialiser (par exemple, le nom de l’animal), appelez impérativement le constructeur du parent avec les paramètres requis via super(...).

Pour accéder aux champs/méthodes masqués.
Si, pour une raison quelconque, vous avez « masqué » un champ ou une méthode du parent et que vous devez quand même y accéder, utilisez super.nomDuChamp ou super.nomDeMethode().

Contraintes et particularités d’utilisation de super

  • L’appel du constructeur parent via super(...) ne peut se faire que dans un constructeur et uniquement en première ligne.
  • Il est impossible d’appeler un constructeur parent en dehors du constructeur d’une sous-classe.
  • Si vous n’appelez pas explicitement super(...), Java essaiera d’appeler le constructeur sans paramètre du parent (s’il existe).
  • Le mot-clé super ne peut pas être utilisé dans des méthodes statiques — seulement dans des méthodes d’instance (non statiques) et dans les constructeurs.
  • Si une méthode ou un champ du parent est private, alors super n’y changera rien : les membres privés ne sont pas accessibles.

5. Exemples pour s’entraîner

Exemple 1. Étendre une méthode avec super

class Animal {
    void makeSound() {
        System.out.println("L'animal émet un son");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        super.makeSound(); // d’abord, on exécute l’action standard
        System.out.println("Le chien aboie : Ouaf-ouaf !");
    }
}

Exemple 2. Appeler le constructeur de la classe de base

class Vehicle {
    String brand;

    Vehicle(String brand) {
        this.brand = brand;
        System.out.println("Véhicule : " + brand);
    }
}

class Car extends Vehicle {
    int year;

    Car(String brand, int year) {
        super(brand); // on appelle le constructeur du parent
        this.year = year;
        System.out.println("Voiture " + brand + ", année : " + year);
    }
}
Car car = new Car("Toyota", 2023);
// Sortie :
// Véhicule : Toyota
// Voiture Toyota, année : 2023

Exemple 3. Erreur classique : on a oublié d’appeler super(...)

class Animal {
    String name;

    Animal(String name) {
        this.name = name;
    }
}

class Cat extends Animal {
    Cat() {
        // super(); // Erreur ! Pas de constructeur Animal() sans paramètre
        // Il faut appeler explicitement super(name)
        super("Chat sans nom");
    }
}

6. Erreurs courantes avec super

Erreur n° 1 : appel de super(...) pas en première ligne du constructeur.
Java exige strictement que l’appel du constructeur parent via super(...) soit la première ligne du constructeur de la sous-classe. Si vous essayez de faire quelque chose avant cet appel (par exemple, afficher un message), le compilateur renverra une erreur.

Erreur n° 2 : pas de constructeur approprié chez le parent.
Si la classe de base n’a pas de constructeur sans paramètre et que vous n’appelez pas un autre constructeur via super(...), le compilateur ne pourra pas générer l’appel par défaut et signalera une erreur.

Erreur n° 3 : tentative d’accéder aux membres privés du parent via super.
Le mot-clé super ne donne pas un accès magique aux champs ou méthodes privés du parent. Si quelque chose est déclaré private, cela reste inaccessible à la sous-classe.

Erreur n° 4 : masquage de champs et méthodes sans compréhension.
Si vous avez déclaré dans la sous-classe un champ ou une méthode portant le même nom que chez le parent et que vous l’oubliez, des résultats inattendus sont possibles. Souvenez-vous toujours que, dans ce cas, l’accès au membre parent se fait uniquement via super.

Erreur n° 5 : utilisation de super dans une méthode statique.
On ne peut pas utiliser super dans les méthodes statiques, car elles n’appartiennent pas à un objet concret.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION