Théorie 1.2.1: héritage #
- L’héritage est parfois un contrat qu’il faut remplir
- ça nous force à ajouter des méthodes obligatoires
- C’est aussi une façon de réutiliser du code
- Par exemple:
public class MonTutoriel2_1 extends Tutoriel2_1 {
public static void main(String[] args) {
new MonTutoriel2_1().valider();
}
-
L’outil de validation au complet devient accessible:
- En héritant de
Tutoriel2_1
- En créant un nouvel objet
MonTutoriel2_1
- En appelant la méthode
valider
sur cet objet
- En héritant de
-
La classe
MonTutoriel2_1
n’a pas à définir la méthodevalider
-
Cette méthode est héritée de
Tutoriel2_1
Hiérarchie de classe #
-
On visualise l’héritage des classes en arbre (ou hiérarchie):
-
Ci-haut, on a par exemple:
DeuxRoues
hérite deVehicule
Mobilette
hérite deDeuxRoues
Moto
hérite deDeuxRoues
-
En java, on utilise le mot clé
extends
. P.ex:
public class DeuxRoues extends Vehicule {
public class Mobilette extends DeuxRoues {
public class Moto extends DeuxRoues {
Trois types de méthodes #
-
Par rapport à l’héritage, il y a trois types de méthodes:
- méthode déclarée
- nouvelle méthode (elle n’existe pas dans la classe parent)
- méthode redéfinie
- nouvelle version d’une méthode déjà qui existe dans la classe parent
- méthode héritée
- méthode qui existe déjà dans la classe parent et qu’on ne redéfinie pas
- méthode déclarée
-
Exemples:
public class Vehicule {
public int nombreDeRoues() {
return 0;
}
public double litresEssenceConsomes(double kilometres) {
return kilometres * consommationLitresParKilometre();
}
- Les méthodes
nombreDeRoues
etlitresEssenceConsomes
sont déclarées - Elles n’existent pas dans une classe parent
public class DeuxRoues extends Vehicule {
@Override
public int nombreDeRoues() {
return 2;
}
- La méthode
nombreDeRoues
est redéfinie- On met l’annotation
@Override
pour indiquer - Cette méthode existe dans la classe parent
Vehicule
- Dans
DeuxRoues
, on veut lui donner un autre comportement
- On met l’annotation
- La méthode
litresEssenceConsomes
est héritée- La classe
DeuxRoues
ne la redéfinie pas - Le comportement défini dans
Vehicule
va s’appliquer
- La classe
Où implanter une méthode? #
-
Considérer p.ex:
-
Il faut se poser la question:
- Est-ce que tous les XXX ont ce comportement?
- On implante la méthode dans la classe la plus haute qui se qualifie
-
Par exemple:
- Est-ce que tous les XXX peuvent miauler?
- la méthode
miauler
va dans la classeChat
- la méthode
- Est-ce que tous les XXX peuvent dormir?
- la méthode
dormir
va dans la classeAnimal
- la méthode
- Est-ce que tous les XXX peuvent miauler?
Où redéfinir une méthode? #
-
Revenons à:
-
Il faut se poser la question:
- Où connaît-on vraiment la réponse?
- On redéfini la méthode à chaque fois que la réponse change
-
Par exemple:
- Où connaît-on le nombre de roues?
- on redéfini
nombreDeRoues
dansDeuxRoues
etQuatreRoues
- mais pas dans
Auto
puisque c’est la même réponse queQuatreRoues
- on redéfini
- Où connait-on la consommation d’essence?
- on redéfini
consommationLitresParKilometre
dans chaque type de véhiculeMoto
,Mobilette
,Auto
,Camion
etFourgonnette
- on redéfini
- Où connaît-on le nombre de roues?
Et les attributs? #
- Il est possible d’hériter d’un attribut, mais il n’est pas possible de redéfinir un attribut.
- Pour cette raison:
- On utilise des accesseurs (getter) pour obtenir la valeur d’un attribut
- comme ça la classe enfant peut modifier la valeur!
- L’héritage n’est généralement pas utile pour représenter les données
- L’héritage est utile pour représenter des variatons de comportement
- On utilise des accesseurs (getter) pour obtenir la valeur d’un attribut
Exemple: litresEssenceConsomes
#
- Considérer la méthode
litresEssenceConsomes
:
public class Vehicule {
public int nombreDeRoues() {
return 0;
}
public double litresEssenceConsomes(double kilometres) {
return kilometres * consommationLitresParKilometre();
}
-
Cette méthode utilise un accesseur (
consommationLitresParKilometre
)- On écrit le calcul dans la classe parent, sans connaître la valeur
-
C’est la classe enfant qui retourne la bonne valeur:
public class Mobilette extends DeuxRoues {
@Override
public double consommationLitresParKilometre() {
return 1.5;
}
-
Ainsi, on a pas besoin de redéfinir
litresEssenceConsomes
-
Le calcul va fonctionner pour tous les types de véhicule, car:
Moto
redéfiniconsommationLitresParKilometre
Mobilette
redéfiniconsommationLitresParKilometre
Auto
redéfiniconsommationLitresParKilometre
- etc.