Héritage

Dans la pratique, une classe est rarement définie depuis zéro. Si on trouve une autre classe qui comporte déjà les fonctionnalités recherchées, il est plus simple de partir de celle-là en héritant de tout ce qu'elle contient.

import java.awt.Point;
 
public class PointPolaire extends Point {
  public double getRayon() {
    return Math.sqrt((double)(this.x*this.x + this.y*this.y));
  }
  public double getAngle() {
    return 2.0*Math.atan(((double)this.y)/(this.getRayon()+(double) this.x));
  }
}

Cet exemple définit un point du plan capable de donner ses coordonnées polaires. Plutôt que de réinventer une telle classe, on part de Point et on ajoute simplement les nouvelles fonctionnalités. La classe obtenue possède les nouvelles méthodes getRayon et getAngle, plus les attributs (x et y) et les méthodes (move, translate, etc) de la classe Point.

Remarque Chaque classe ne peut hériter que d'une seule autre classe. Le langage Java ne permet pas l'héritage multiple, bien que d'autres langages le proposent (par exemple le C++).

Seuls les constructeurs ne sont pas directement hérités. Notre exemple précédent possède donc uniquement un constructeur par défaut, ce qui est franchement insuffisant. Ajoutons un constructeur utile :

public class PointPolaire extends Point {
  ...
  public PointPolaire(int rayon, int angle) {
    super((int) rayon*Math.cos(angle), (int) rayon*Math.sin(angle));
  }
}

La première ligne d'un tel constructeur doit mentionner le mot-clé super suivi d'arguments. Ceci permet d'appeler le constructeur de la classe de base pour qu'il se charge d'initialiser la partie héritée de l'objet.

Si vous oubliez cette première ligne, le constructeur sans argument de la classe de base sera tout de même invoqué. Si aucun constructeur sans argument n'est défini dans la classe de base, une erreur sera signalée à la compilation.

Parfois les fonctionnalités héritées ne sont pas compatibles avec la nouvelle classe. On peut alors désirer remplacer les méthodes obsolètes par une version plus adéquate : c'est une redéfinition (à ne pas confondre avec une surcharge).

public class PointPolaire extends Point {
  ...
  @Override
  public String toString() {
    return "(" + this.getRayon() + " ; " + this.getAngle() + ")";
  }
}

Remarque Une redéfinition n'a lieu que si la signature de la nouvelle méthode reprend exactement la signature d'une méthode héritée. En cas de divergence, la nouvelle méthode sera interprétée comme une simple surcharge si vous oubliez l'annotation @Override.

On peut encore invoquer l'ancienne version de la méthode en utilisant le mot-clé super à la place de this.

public class PointPolaire extends Point {
  ...
  public String toRectangularString() {
    return super.toString();
  }
}

  1. Documentation. La description de l'API Java est disponible en version locale ou sur le site d'Oracle. Utilisez cette documentation pour répondre aux questions suivantes :
    • Dans quel package peut-on trouver la classe String ? De quelle classe hérite-t-elle ? Combien de méthodes sont transmises par la classe mère ? Sur celles-ci, combien sont redéfinies ?
    • Écrivez un programme qui affiche tous les argument de sa ligne de commande, convertis en majuscules. Trouvez dans la classe String de quoi vous simplifier le travail.
    • Écrivez un programme qui prend un entier exprimé en base 8 sur la ligne de commande, puis affiche la même valeur en base 16. Trouvez dans la classe Integer de quoi vous simplifier le travail.
  2. Grisaille. Définissez une classe Gris qui dérive de la classe Color mais ne permet de créer que des gris (c'est à dire des couleurs où les trois composantes sont égales). Pouvez-vous utiliser un objet de la classe Gris avec la méthode setBackground pour choisir la couleur de fond d'un composant ?

  3. Métrique. La classe Paper sert à représenter la géométrie d'une feuille de papier (dans le but de faire des impressions). Malheureusement, cette classe utilise le système impérial obsolète pour toutes ses mesures.

    • Écrivez la définition d'une classe dérivée de Paper, dont le constructeur sans argument crée une feuille au format A4 avec une marge de 1,5cm de chaque coté.
    • Ajoutez une méthode getMetric... pour chaque méthode get..., utilisant les millimètres plutôt que les 1/72ème de pouce.
    • Idem pour les méthodes set....
    • Testez votre travail à chaque étape par un court programme !

  4. Nuancier. On souhaite écrire une application qui se comporte comme un nuancier : elle permet de voir des couleurs côte à côte.

    Pour cela, nous allons commencer par définir un composant graphique spécialisé nommé Nuance. Celui-ci devra avoir une taille préférée de 100 pixels de large par 100 pixels de haut, et devra indiquer les composants RVB de sa couleur de fond dans sa partie haute. De quelle classe pouvez-vous hériter ?

    Écrivez une application qui prend une liste de couleurs sur la ligne de commande (au format #RRVVBB) et qui affiche ces couleurs horizontalement à l'aide du composant défini plus haut.

    bob@box:~$ java Nuancier "#88E900" "#0088E9" "#E90088"
    

    Remarque Pour que la fenêtre prenne une taille adaptée à son contenu plutôt qu'une taille arbitraire, utilisez la méthode pack à la place de la méthode setSize.

retour à la page d'accueil

retour au sommet