CHAPITRE 3
Héritage et polymorphisme
Partie 1: Héritage
1. L’héritage (1): Concept
• L’héritage constitue l’un des fondements de base de la
POO.
• Il permet le partage et la réutilisation de propriétés entre
les objets.
• La relation d’héritage est une relation de généralisation /
spécialisation.
• L’héritage permet de définir des classes sous forme d’une
hiérarchie (les fils héritent de leurs parents).
• Une classe dérivée permet de préciser le comportement
d’un sous-ensemble d’objet.
• Une classe peut avoir plusieurs sous classes.
• Une classe ne peut avoir qu'une seule classe mère.
3
1. L’héritage (2): Concept
• La classe dérivée:
• hérite de tous les membres de sa superclasse (classe
mère).
• Elle permet de les spécialiser (redéfinir).
• Elle permet d’ajouter de nouveaux attributs et/ou de
nouvelles méthodes.
• Pour le programmeur:
• il s'agit d'indiquer, dans la sous-classe, le nom de la
superclasse dont elle hérite précéder par le mot réservé
extends.
• Par défaut toutes classes Java hérite de la classe
Object.
4
1. L’héritage (3):Concept
Classe Véhicule
Genre
Immatriculation
propriétaire Superclasse
Généralisation
Spécialisation
Avancer ()
S_arrêter()
Lien d’héritage
Sous-classe
Nb-places Tonnage
Nb-portes Type_chargement
5
2. L’héritage: Exemple (1)
Supposons que nous disposons de la classe Point vue
dans le cours précédent et que nous souhaitons créer
une classe PointCol afin de manipuler des points colorés
dans un plan.
6
2. L’héritage: Exemple (2)
La définition de la classe PointCol :
Précise au
compilateur que la
class PointCol extends Point {
private String couleur;
classe PointCol
dérive de la classe
public void colorer (String couleur) { Point
this.couleur = couleur;
}
7
2. L’héritage: Exemple (3)
• Nous pouvons créer des objets de type PointCol:
8
2. L’héritage: Exemple (4)
Un objet de type PointCol peut alors faire appel
Aux méthodes publiques de PointCol: colorer
Et aux méthodes publiques de la classe Point : déplacer
et afficher
9
2. L’héritage: Exemple (5)
La classe Point
class Point {
private int x;
private int y;
10
2. L’héritage: Exemple (2)
La classe PointCol
11
2. L’héritage: Exemple (2)
Une classe utilisant un objet de type pointCol
Class Test {
public static void main (String args[]) {
PointCol pc = new PointCol ();
pc.afficher();
pc.colorer(" Noir ");
pc.afficher(); Coordonnées: 0 0
pc.deplace(2, 5); Coordonnées: 0 0
pc.afficher(); Coordonnées : 2 5
}
}
12
3. Accès aux membres de la classe mère (1)
13
3. Accès aux membres de la classe mère (2)
• La 1ère solution :
14
3. Accès aux membres de la classe mère (3)
• Une autre solution :
class Point {
protected int x;
protected int y; Le mot clé
// les méthodes de la classe point
…… protected signifie
}
class PointCol extends Point { que ces attributs
private String couleur; sont accessibles à
Public void colorer (String couleur) { partir des méthodes
this.couleur = couleur;
des classes
}
Public void afficheTout() { dérivées
System.out.println("coordonnées:"+x+" "+y);
System.out.println("couleur:" + couleur);
}
}
15
3. Accès aux membres de la classe mère(4)
17
4.Construction des objets dérivés (2)
Supposons que
La classe Point dispose d’un constructeur à deux arguments
Point (int x, int y) qui initialise les coordonnées x et y .
Nous voulons doter la classe PointCol d’un constructeur à
trois arguments
Comment pourrions nous le faire ?
Il faut savoir que
18
4.Construction des objets dérivés (3)
Deux possibilités:
1. Initialiser les trois champs : x, y et couleur.
Attention: Si les champs x et y sont privés, il faut disposer de
méthodes d’altération Setters) pour pouvoir les modifier
2. Utiliser le constructeur de la classe de base Point. Le
constructeur de PointCol pourrait:
• Initialiser le champs couleur (accessible)
• Appeler le constructeur de Point pour initialiser x et y
Attention
Si un constructeur d’une classe dérivée appelle un
constructeur s’une classe de base, il utilise le mot clé
super et cette instruction doit obligatoirement se faire en
premier.
19
4.Construction des objets dérivés (4)
Première solution
20
4.Construction des objets dérivés (5)
Deuxième solution
21
4.Construction des objets dérivés (6)
22
4.Construction des objets dérivés (7)
Cas 1. La classe de base ne possède aucun constructeur
23
4.Construction des objets dérivés (8)
24
4.Construction des objets dérivés (9)
Exemple 1
Class A
{public A(){…} // constructeur 1 de A
public A (int n) //Constructeur 2 de A
}
25
4.Construction des objets dérivés (10)
Exemple 2
Class A Erreur de compilation !
{public A (int n) //Constructeur de A
} Le constructeur par
défaut de B cherche un
Class B extends A
constructeur sans
{ arguments de A.
…// pas de constructeur Comme A possède un
} constructeur avec
Comment se fait la création d’un objet de B ? argument, il n’est plus
question d’utiliser le
constructeur par défaut
de A
26
4.Construction des objets dérivés (11)
Exemple 3
Class A
{… //Pas de constructeur
} B b = new B();
constructeur par
Class B extends A
défaut de B
{
…// pas de constructeur
appelle
} constructeur par
Comment se fait la création d’un objet de B ? défaut de A
27
5. Initialisation d’un objet dérivé (1)
Dans une classe simple (non dérivée) l’initialisation des
attributs d’un objet se fait dans l’ordre suivant
initialisation par défaut (implicite)
initialisation explicite (s’il y en a )
Exécution du corps du constructeur
Exemple:
class A{
public A (){…} -Initialisation implicite des champs n et p
private int n= 10;
de l’objet a à la valeur 0;
private int p;
{
… - L’initialisation (explicite) du champs n à la
A a = new A(); valeur figurant dans sa déclaration, soit 10.
28
5. Initialisation d’un objet dérivé (2)
29
6. Dérivations successives
Animal
Chien Canari
Chat
30
6. Redéfinition de méthodes (1)
La surcharge (surdéfinition) de méthode à l’intérieur d’une
même classe corresponde à des méthodes de même nom
mais de signatures différentes.
La signature d'une méthode
class Affiche { comprend le nom de la
public void affval (int x){
System.out.println("nombre entier="+x);
classe, le nom de la méthode
} et les types des paramètres.
public void affval (double x){
System.out.println("nombre réel="+x);
}
} Il n'est pas possible d'avoir
deux méthodes de même nom
class Affiche {
dont tous les paramètres sont
public float convert (int x){ identiques et dont seul le type
return ((float)x); retourné diffère.
} Erreur de compilation
public double convert (int x){
return ((double)x); « Duplicate method »
}
}
31
6. Redéfinition de méthodes (2)
32
6. Redéfinition de méthodes (3)
Exemple des classes Point et PointCol
class Point {
private int x , y;
……
p.afficher();
public void afficher() Affiche les
{
System.out.println("je suis un point de coordonnées de
coordonnées:"+x+" "+y);
}
l’objet p.
…..
}
class PointCol extends Point { pc.afficher();
private String couleur;
… Affiche les
/* Ici, aucune méthode
ne se nomme afficher
coordonnées de
*/ l’objet pc (n’affiche
}
……..
pas la couleur);
Point p; PointCol pc;
……
33
6. Redéfinition de méthodes (4)
34
6. Redéfinition de méthodes (5)
Exemple des classes Point et PointCol
35
6. Redéfinition de méthodes (6)
Exemple des classes Point et PointCol
36
6. Redéfinition de méthodes (7)
37
7. Redéfinition de méthodes et dérivations
successives
Soit une méthode f définie dans A et redéfinie dans les classes C et D
Appel de f dans A conduit à l’appel de f de … A
A*
B C*
F
D* E
38
8. Surcharge et héritage
Une classe peut surcharger(surdéfinir) une méthode d’une
classe de base
Exemple
class A appelle f de A
a.f(n); //
{public void f (int n) {…}
…..
a.f(x); // Erreur de compilation!
}
Class B extends A
{ public void f (float x) {….}
b.f(n); // appelle f de A
…
} b.f(x); // appelle f de B
A a; B b;
int n, float x;
…
39
LOGO
Valeur de retour
class A
{public void f (int n) {…}
…..
}
Class B extends A
{ public float f (float x) {….}
…
}
Redéfinition ou surcharge?
41
9. Contraintes portant sur la redéfinition (2)
Valeur de retour
class A Ni l’un ni l’autre !
{public void f (int n) {…}
….. Ce n’est pas une
surcharge de la
}
méthode f puisque la
Class B extends A signature est la
{ public float f (int n) {….} même.
… Ce n’est pas non plus
une redéfinition parce
} que les types de
Redéfinition ou surcharge ? retour sont différents.
42
9. Contraintes portant sur la redéfinition (3)
Les droits d’accès
class A La redéfinition
{public void f (int n) {…} d’une méthode ne
….. doit pas diminuer
} les droits d’accès
Class B extends A (la visibilité) à
cette méthode.
{ private void f (int n) {….}
En revanche , elle
…
peut les
} augmenter
Correct ou incorrect ?
Incorrect ! Rejeté par le compilateur
Si c’était accepté, un objet de la classe A aurait accès à la méthode f alors
qu’un objet de la classe B n’y aurait plus accès.
La classe B romprait le Contrat établit par la classe A
43
10. Règles générale de redéfinition et de surcharge
(surdéfinition)
• Si une méthode d’une classe dérivée a la même signature
qu'une méthode d’une classe ascendante:
Les valeurs de retour des deux méthodes doivent être
exactement de même type
Le droit d’accès de la méthode de la classe dérivée ne doit
pas être moins élevé que celui de la classe ascendante
Partie 2: Polymorphisme
1. Le polymorphisme (1): Concept
Le polymorphisme est un concept extrêmement puissant en
POO, il permet de manipuler des objets sans en connaître
tout à fait le type tout en se basant sur la relation d’héritage.
48
2. Les bases du polymorphisme (1)
Soient les classes Point et PointCol suivantes:
49
2. Les bases du polymorphisme (2)
class TestPolymorphisme { 3
Public static main (String args[])
{
Point p; p 5
p = new Point(3,5);
//Java autorise cette affectation
p = new PointCol (4,9,"Vert");
}
} 4
p 9
"vert"
Règle 1: Java permet à une variable
objet l’affectation d’une référence à
objet d’un type dérivé
50
2. Les bases du polymorphisme (3)
appelle la méthode afficher de la classe
class TestPolymorphisme {
Public static main (String args[])
Point
{ je suis un point de coordonnées: 3 5
Point p;
p = new Point(3,5);
p.afficher(); appelle la méthode afficher de la classe
p = new PointCol (4,9,"Vert"); PointCol
p.afficher(); je suis un point de coordonnées: 3 5
} vert
} L’instruction p. afficher() se base non pas
sur le type de la variable p mais sur le type
effectif de l’objet référencé par p au
moment de l’appel car celui-ci peut évoluer
dans le temps. Ce choix qui se fait au
Règle 2: Le choix de la méthode
moment de l’exécution et non pas au
appelée se fait selon le type
moment de la compilation s’appelle
effectif de l’objet référencé au
ligature dynamique (ou liaison
moment de l’exécution
dynamique).
51
2. Les bases du polymorphisme (4)
En résumé:
52
3. Généralisation du polymorphisme
à plusieurs classes (1)
• A a; B b; C c; D d; E e; F f;
A
B C
F
D E
a = b; OUI a = e; OUI
b = e; OUI
a = c; OUI b = a; NON
c= f; OUI
c = d; NON a =f; OUI d = c; NON
a = d; OUI b = d; OUI
53
3. Généralisation du polymorphisme
à plusieurs classes (2)
Soit une fonction f définie/redéfinie dans les classes comportant
une étoile. Quelle est la méthode appelée dans les cas suivant?
A*
B C *
F
D * E
55
4. Polymorphisme, redéfinition et surcharge
(2)
Explication:
Bien que a.f(n) et b.f(n) appliquent toutes les deux une méthode f à un objet de
type B, elles n’appellent pas la même méthode.
Pour l’instruction a.f(n), le compilateur recherche la meilleure méthode (selon
les règles de surdéfinition) parmi toutes les méthodes de la classe A ou ses
ascendantes. Ici, c’est la méthode void f(float x) de A. Une fois la bonne
méthode trouvée, sa signature et son type de retour sont définitivement figés.
Lors de l’exécution, on se base sur le type de l’objet référencé par a pour
rechercher une méthode ayant la signature et la valeur de retour voulus. On
aboutit alors à la méthode f(float) de B, et ce malgré l’existence dans B d’une
méthode plus appropriée au type de l’argument effectif.
56
4. Polymorphisme, redéfinition et surcharge
(2)
L’utilisation simultanée de la
surdéfinition et de la redéfinition
peuvent conduire à des situations
complexes.
Il est donc conseillé de les utiliser
prudemment et de ne pas en abuser.
57
5. Conversion des arguments effectifs: cas
d’arguments de type objet (1)
Cas 1.Méthode non surdéfinie et non redéfinie
class A
{ public void indentite ()
{ System.out.println(" Objet de type A ");}
}
class B extends A
{// pas de redéfinition de la méthode identité
}
class Util
{
static void f(A a) //objet de type A en argument
{ a.identite();}
}
A a = new A(…); B b = new B(…);
Util.f(a); // Il affiche « objet de type A »
Util.f(b);// il affiche « objet de type A »
58
5. Conversion des arguments effectifs: cas
d’arguments de type objet (2)
Cas 2.Méthode non surdéfinie et redéfinie
class A
{ public void indentite ()
{ System.out.println(" Objet de type A ");}
}
class B extends A
{public void indentite ()
{ System.out.println(" Objet de type B ");}
}
class Util
{
static void f(A a)
{ a.identite();}
}
Public static void main(String []args){
A a = new A(); B b = new B();
Util.f(a); // il affiche « objet de type A »
Util.f(b); // il affiche « objet de type B »
}}
59
5. Conversion des arguments effectifs: cas
d’arguments de type objet (3)
Cas 3.Méthode surdéfinie (exemple simple)
class A {…….}
class B extends A {….…}
class Util
{
static void f(int n, B b) {….}
static void f(float x, A a){….}
}
…
A a = new A(); B b = new B(); int n; float x;
Exemple:
class Point{…}
class PointCol extends Point {…}
…
PointCol pc;
pc = new Point (…)// erreur de compilation
Remarque: Pour s’assurer qu’un objet est bien d’une classe donnée, il suffit
d’utiliser l’opérateur instanceof
65
8. La super-classe Object (2)
66
10. Utilisation de méthodes de la classe Object
La classe Object comporte quelques méthodes qu’on peut soit utiliser telles
quelles soit les redéfinir. Les plus importantes sont :
toString : fournit une chaine contenant le nom de la classe à laquelle
appartient l’objet ainsi que l’adresse de l’objet en hexadecimal
Point p = new Point (3,5);
System.out.println(" p = " + p.toString() ); // affiche
par exemple p = Point@fc17aedf
getClass() :retourne Class Nom_de_la_classe
System.out.println (p.getClass()); //Class Point
hashCode(): fournit le code de hachage correspondant à la valeur de
l’objet utiliser les adresses des objets comme comme code de hachage).
equals: compare les adresse de deux objets.
Remarque:
toute classe qui redéfinit equals() doit aussi redéfinir hashCode(). En
effet, deux objets égaux par equals() doivent avoir la même valeur
de hachage par hashCode(). Ces contraintes (sur equals() et
hashCode() doivent être respectées, afin d'assurer à l'utilisateur que
les méthodes qui les utilisent (par exemple, Collections.sort, etc.) font
bien ce qu'elles sont sensées faire.
67
10. Utilisation de méthodes de la classe Object
68
11. Rédéfinition de equals et hashcode
class Point {
private int x , y;
public Point (int absc, int ord)
{x = absc;
y = ord;
}
public void deplacer (int dx, int dy)
{x = x + dx;
y = y + dy;
}
public void afficher()
{
System.out.println("je suis un point de coordonnées:"+x+" "+y);
}
public int hashCode ()
{ return x+y ; }
Exemple:
Point p = new Point();
Object o;
…
o= p;
70
13. Les membres protégés (1)
71
13. Les membres protégés (2)
Exemple: A
class A
{…. B C
protected int n ;
}
B accède à n de A
D accède à n de B et de A
C accède à n de A
Mais C n’accède pas à n de B (sauf si B et C sont dans le même paquetage)
car aucun lien ne dérivation ne relie C à B
72
14. Héritage et tableaux
73
15. Polymorphisme et tableaux
La polymorphisme peut s’appliquer à des tableaux
d’objets. Si B dérive de A, un tableau d’objets de type
B est compatible avec un tableau d’objets de type A
class B extends A {…….}
A ta[];
B tb[];
……
ta = tb; // OK car B dérive de A
tb = ta; // erreur