Dans ce chapitre, nous allons parler d’une notion importante appelée héritage. L’héritage permet de spécialiser une classe. Par spécialisation, j’entends ajouter ou modifier le comportement d’une classe, étendre son fonctionnement.
C’est encore un peu flou, j’imagine ? Commençons par du concret pour mieux comprendre.
Spécialisation
De quoi est composé un véhicule ?
C’est assez compliqué, il en existe beaucoup de différents ! Des voitures, des camions, des bateaux, des avions, des vélos, etc.
En fonction de celui auquel on s’intéresse, on peut trouver différentes fonctionnalités :
rouler ;
freiner ;
voler ;
pédaler ;
etc.
Naturellement, les composants sont aussi très variés :
vitesse ;
consommation ;
taille des pneus ;
capacité de la benne (pour un camion) ;
nombre de places en première classe (pour un TGV) ;
etc.
Si nous voulons représenter un véhicule dans du code, il faut essayer de trouver les composants en commun entre tous les véhicules.
On en trouve finalement très peu :
nom du modèle ;
description ;
fabricant ;
date de mise en circulation ;
couleur ;
vitesse ;
dimensions ;
poids.
Difficile d’en trouver d’autres qui fonctionnent dans tous les cas. Même en ne retenant que ceux-là, peut-être qu’un composant ne marchera pas pour un autre type de véhicule.
Pour les fonctionnalités, c’est encore plus compliqué :
Démarrer ;
Arrêter...
... Et je n’en vois pas d’autres !
Voici l'UML :

Et le code correspondant :
package com.cursan.garage;
public class Vehicle {
private String modelName;
private String description;
private String manufacturer;
private int year;
private String color;
private int speed;
private int[] dimensions = new int[3];
private int weight;
public Vehicle(String modelName, String description, String manufacturer, int yeah, String color, int speed, int[] dimensions, int weight) {
this.modelName = modelName;
this.description = description;
this.manufacturer = manufacturer;
this.year = year;
this.color = color;
this.speed = speed;
this.dimensions = dimensions;
this.weight = weight;
}
public void start() {
System.out.println("Je suis " + modelName + " et je démarre");
}
public void stop() {
System.out.println("Je suis " + modelName + " et je m'arrête");
}
... getters ...
}
Nous allons prendre le cas d‘un garage qui vend beaucoup de véhicules d’occasion : voitures, motos, camions, bateaux et même quelques petits avions personnels.
Pour avoir un système efficace de recherche, les attributs trouvés ci-dessus ne seront pas suffisants.
Quelle solution utiliser ?
Eh bien l’héritage ! L’héritage sert à représenter exactement ce type de problématique. Nous avons une classe mère Vehicle
, et nous allons créer des classes enfants : Car
, Bike
, Truck
, Boat
, Plane
, etc.
Une classe enfant reprend toutes les fonctionnalités de son parent. Elle va pouvoir lui ajouter du comportement.
Prenons une voiture. Ce sera beaucoup plus facile de créer un logiciel de recherche si nous stockons :
le nombre de portes ;
la consommation ;
le type de moteur ;
les options.
De la même façon, avec une voiture, on peut, par exemple :
allumer les phares ;
ouvrir le coffre.
Ce n'est pas possible avec un vélo.
Voici comment faire cela avec du code :
package com.cursan.garage;
import java.util.ArrayList;
import java.util.List;
public class Car extends Vehicle {
private int door;
private int literPer100km;
private String motor;
private List<String> options = new ArrayList<String>();
public Car(String modelName, String description, String manufacturer, int yeah, String color, int speed, int[] dimensions, int weight, int door, int literPer100km, String motor, List<String> options) {
super(modelName, description, manufacturer, yeah, color, speed, dimensions, weight);
this.door = door;
this.literPer100km = literPer100km;
this.motor = motor;
this.options = options;
}
public void startHeadlight() {
System.out.println("J'allume mes phares");
}
public void openTrunk() {
System.out.println("J'ouvre mon coffre");
}
... getters ...
}
Et l'UML correspondant :

En utilisant une variable de type Car
dans le code, nous avons accès aux méthodes de Car
, mais aussi à celles de Vehicle
.

On peut ainsi représenter Truck
, Bike
, Boat
et Plane
comme enfants de Vehicle
. Ils auront en commun le comportement de Vehicle
, mais chacun aura sa spécialisation.
Quelques détails sur le code
On va revenir sur plusieurs lignes intéressantes de la classe Car
.
public class Car extends Vehicle {
Avec cette ligne, on précise que la classe Car
étend la classe Vehicle
.
public Car(String modelName, String description, String manufacturer,
int yeah, String color, int speed, int[] dimensions, int weight,
int door, double literPer100km, String motor, List<String> options)
{
super(modelName, description, manufacturer, yeah, color, speed, dimensions, weight);
this.door = door;
this.literPer100km = literPer100km;
this.motor = motor;
this.options = options;
}
C'est le constructeur de Car
. Il prend en paramètre les attributs de Vehicle
et les siens. La ligne super(...)
permet de passer les arguments au constructeur de Vehicle
.
Il ne faut pas oublier qu'une voiture reste un véhicule. Pour fabriquer une voiture, il faut donner les informations communes à tous les véhicules ET celles spécifiques aux voitures.
Revenons à notre projet
Pour notre projet, nous souhaitons avoir des informations supplémentaires pour quelques produits.
Pour les télévisions, nous voulons :
une taille d'écran ;
une technologie de dalle (LED, LCD, Plasma).
Pour les réfrigérateurs, nous voulons :
une capacité en litres ;
la présence ou non d'un bac freezer.
Je commence par vous donner l'UML. Essayez de coder la solution à partir de celui-ci.

Le code de Television
et Fridge
.
package com.cursan.homeshop;
public class Television extends Product {
private int size;
private String slabType;
public Television(String name, String description, double price, int size, String slabType) {
super(name, description, price);
this.size = size;
this.slabType = slabType;
}
public int getSize() {
return size;
}
public String getSlabType() {
return slabType;
}
}
package com.cursan.homeshop;
public class Fridge extends Product {
private int liter;
private boolean freezer;
public Fridge(String name, String description, double price, int liter, boolean freezer) {
super(name, description, price);
this.liter = liter;
this.freezer = freezer;
}
public int getLiter() {
return liter;
}
public boolean isFreezer() {
return freezer;
}
}