Vous êtes sur la page 1sur 79

LOGO

Université Saad Dahlab


de Blida

CHAPITRE 3
Héritage et polymorphisme

Disponible sur: https://sites.google.com/a/esi.dz/informatiqueblida/


Mme BOUTOUMI
L2
2019- 2020
LOGO

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
2. L’héritage: les notions (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.

 La classe PointCol peut disposer des mêmes attributs et


fonctionnalités que la classe Point auxquels on ajoute un
attribut couleur représentant la couleur d’un point et une
méthode colorer permettant d’attribuer une couleur à un
point.

5
2. L’héritage: les notions (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;
}

6
2. L’héritage: les notions (3)
• Nous pouvons créer des objets de type PointCol:

PointCol pc = new PointCol();

Comment l’objet pc a-t-il pu être créé sans avoir défini


de constructeur dans la classe PointCol ?

En utilisant le constructeur par défaut

7
2. L’héritage: les notions (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

Un objet d’une classe dérivée accède aux


membres publics de sa classe de base

8
Exemple (1)
La classe Point

class Point {
private int x;
private int y;

public void initialiser (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);
}
}

9
Exemple (2)
La classe PointCol

class PointCol extends Point {


private String couleur;

public void colorer (String couleur) {


this.couleur = couleur;
}
}

10
Exemple (3)
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
}
}

11
3. Accès aux membres de la classe mère (1)

• Nous voulons doter la classe PointCol d’une méthode


afficherTout qui affiche non seulement les coordonnées du
point mais aussi sa couleur.

class PointCol extends Point {


private String couleur;

public void colorer (String couleur) {


Correct ou
this.couleur = couleur; faux ?
}
public void afficheTout() {
FAUX !
System.out.println("coordonnées:"+x+" "+y);
System.out.println("couleur:" + couleur);
}

12
3. Accès aux membres de la classe mère (2)

• La 1ère solution :

class PointCol extends Point {


private String couleur;

public void colorer (String couleur) { appel à la méthode


this.couleur = couleur; public void afficher ()
}
de la classe point
public void afficheTout() {
afficher();
System.out.println("couleur:" + couleur);
}

13
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);
}
}

14
3. Accès aux membres de la classe mère(4)

• Les items (attributs ou méthodes) private d’une


classe sont inaccessibles, non seulement en
dehors de la classe, mais aussi à ses classes
dérivées.
• Les items protected d’une classe, ne sont pas
accessibles en dehors de la classe mais ils le sont
pour ses classes dérivées.
• Les attributs sont toujours privés.
• Pour permettre l’accès d’une classe aux attributs de
sa classe mère, il faut lui fournir des méthodes
d’accès protected si elle ne sont pas déjà
publiques. 15
4.Construction des objets dérivés (1)
 Rappel:
 Dans le cas d’une classe simple (non dérivée), la création
d’un objet par new se fait par l’appel du constructeur ayant
la signature voulue (nombre et types des arguments).
 Si aucun constructeur ne convient, on obtient une erreur de
compilation sauf si la classe ne dispose d’aucun
constructeur. Dans ce cas, on utilise un constructeur par
défaut.

 Comment se fait la construction d’objets dans le cas


d’une classe dérivée ?

16
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

En java, le constructeur de la classe dérivée doit prendre


en charge l’intégralité de la construction de l’objet

17
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.
18
4.Construction des objets dérivés (4)
Première solution

class Point { class PointCol extends Point {


private int x; private String couleur;
private int y;
public Point () public PointCol (int x, int y, String couleur)
{} {
setX(x);
public Point (int x, int y)
setY(y);
{this.x = x;
this.y = y; this.couleur = couleur;
} }
public void setX (int x) // les autres méthodes
{this.x = x; }
}
public void setY (int y)
{this.y = y;
}
// les autres méthodes
}

19
4.Construction des objets dérivés (5)
Deuxième solution

class Point { class PointCol extends Point {


private int x; private String couleur;
private int y;
Public Point (int x, int y)
Public PointCol (int x, int y, String
{this.x = x;
couleur) {
this.y = y;
} Super(x,y);
// les autres méthodes this.couleur = couleur;
} }
// les autres méthodes
}

20
4.Construction des objets dérivés (6)

 Remarque: Une classe peut dériver d’une classe


qui dérive elle-même d’une autre classe. Dans ce
cas, l’appel par super ne concerne que le
constructeur de la classe de base du niveau
immédiatement supérieur.
 Nous avons vu à travers l’exemple, le cas général où
la classe dérivée et la classe de base possèdent
chacune un constructeur. Examinons les autres cas:
 La classe de base ne possède aucun constructeur
 La classe dérivée ne possède aucun constructeur

21
4.Construction des objets dérivés (7)
Cas 1. La classe de base ne possède aucun constructeur

Il est possible d’appeler le constructeur de la classe de


base:
Class A
{….// aucun constructeur
}
Class B extends A
{
public B(..)// constructeur de B
{super ();

}
}

22
4.Construction des objets dérivés (8)

Cas 2. La classe dérivée ne possède aucun


constructeur

Deux cas possibles:


1. Si la classe de base possède un constructeur
avec argument, elle doit aussi avoir un
constructeur sans argument qui sera appelé par le
constructeur par défaut de la classe dérivée
2. Si la classe de base ne possède aucun
constructeur, aucun problème ne se pose, c’est
son constructeur par défaut qui sera appelé

23
4.Construction des objets dérivés (9)

Cas 2. La classe dérivée ne possède aucun


constructeur

Exemple 1
Class A
{public A(){…} // constructeur 1 de A
public A (int n) //Constructeur 2 de A
}

Class B extends A B b = new B();


{
…// pas de constructeur
} constructeur par
Comment se fait la création d’un objet de B ? défaut de B appelle le
constructeur 1 de A

24
4.Construction des objets dérivés (10)

Cas 2. La classe dérivée ne possède aucun


constructeur

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
25
4.Construction des objets dérivés (11)

Cas 2. La classe dérivée ne possède aucun


constructeur

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

26
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{
private int n= 10; -Initialisation implicite des champs n et p
private int p;
de l’objet a à la valeur 0;
public A (){…}
{
… - L’initialisation (explicite) du champs n à la
A a = new A(); valeur figurant dans sa déclaration, soit 10.

- Exécution des instruction du constructeur.

27
5. Initialisation d’un objet dérivé (2)

Dans une classe dérivée ( class B extends A {…}), la


création d’un objet se déroule comme suit:

1. Allocation mémoire pour un objet de type B


2. Initialisation implicite de tous les champs de B
3. Initialisation explicite des champs hérités de A
(éventuellement)
4. Exécution du corps du constructeur de A
5. Initialisation explicite des champs propres à B
(éventuellement)
6. Exécution des corps du constructeur de B

28
Exercice 1: Quels résultat fournit ce programme
Class A {
public int n, p=10;
public A(int nn){
System.out.println(" Entrée Constructeur de A : n=" + n + " p=" + p);
n=nn;
System.out.println(" Sortie Constructeur de A : n=" + n + " p=" + p);
}
}
Class B extends A {
public int q= 25;
public B(int n, int pp){
super(n);
Solution:
System.out.println(" Entrée Constructeur de B : n=" + n + " p= " + p + " q= " + q);
Entrée Constructeur de A : n=0 p=10
p=pp; q=2*n;
Sortie Constructeur de A : n=5 p=10
System.out.println(" Sortie Constructeur de B : n=" + n + " p=" + p + " q= " + q);
Entrée Constructeur de A : n=0 p=10
}
Sortie Constructeur de A : n=5 p=10
} Entrée Constructeur de B : n=5 p= 10 q= 25
Class Test { Sortie Constructeur de B : n=5 p=3 q= 10
public static void main (String args[]) {
A a = new A (5 );
B b = new B(5,3);
}} 29
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 »
}
}
30
6. Redéfinition de méthodes (2)

 Une classe dérivée peut redéfinir une méthode


d’une classe de base.
 La nouvelle méthode ne sera utilisable que par la
classe dérivée ou ses descendantes (ses classes
dérivées) mais pas par ses ascendantes.
 Une classe dérivée peut aussi redéfinir une
méthode, c’est-à-dire, modifier le corps des
instructions d’une méthode sans modifier sa
signature ni son type de retour. Dans ce cas la
nouvelle méthode se substitue à la méthode de la
classe de base.

31
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 coordonnées de
ne se nomme afficher
*/ l’objet pc (n’affiche
}
……..
pas la couleur);
Point p; PointCol pc;
……

32
6. Redéfinition de méthodes (4)

Dans la classe PointCol il y avait la méthode afficherTout


qui permettait d’afficher la couleur en plus des
coordonnées.

Puisque les méthodes afficher et afficherTout font le même


travail (afficher les valeurs des attributs de l’objet), il
serait logique de leur donner le même nom.

En Java cela s’appelle redéfinition de méthode. Une


méthode de la classe dérivée peut avoir la même
signature et le même type de retour qu’une méthode
de la classe de base avec un corps différent.

33
6. Redéfinition de méthodes (5)
Exemple des classes Point et PointCol

class PointCol extends Point {


private String couleur;

public void colorer (String couleur) {


this.couleur = couleur;
}
public void afficher() {
afficher(); Ceci va provoquer un appel
System.out.println("couleur:" récursif à la méthode afficher de la
+ couleur);
} classe PointCol. Pour préciser
qu’on souhaite appeler la méthode
afficher de la classe point on utilise
le mot clé super

34
6. Redéfinition de méthodes (6)
Exemple des classes Point et PointCol

class PointCol extends Point {


private String couleur;

public void colorer (String couleur) {


this.couleur = couleur;
}
public void afficher() {
super.afficher();
System.out.println("couleur:" + couleur);
}

35
6. Redéfinition de méthodes (7)

 La surcharge (surdéfinition) cumule plusieurs


méthodes de même nom avec des signatures
différentes.
 La redéfinition d'une méthode héritée doit
impérativement conserver la déclaration de la
méthode de base (type et nombre de paramètres et
la valeur de retour doivent être identiques) et fournir
dans une sous-classe une nouvelle implémentation
de la méthode.
 Si la signature de la méthode change, ce n'est
plus une redéfinition mais une surcharge
(surdéfinition).

36
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

Appel de f dans B conduit à l’appel de f de … A


Appel de f dans C conduit à l’appel de f de … C
Appel de f dans D conduit à l’appel de f de … D
Appel de f dans E conduit à l’appel de f de …
A
Appel de f dans F conduit à l’appel de f de …
C

A*

B C*

F
D* E
37
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;

38
LOGO

L’utilisation simultanée de la surcharge


(surdéfinition) et la redéfinition peut
conduire à des situations complexes qu’il
vaut mieux éviter en faisant une bonne
conception des classes
9. Contraintes portant sur la redéfinition (1)

Valeur de retour
class A
{public void f (int n) {…}
…..
}
Class B extends A
{ public float f (float x) {….}

}
Redéfinition ou surcharge?

40
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.

41
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
42
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

• Si ces deux conditions sont respectée, on est dans le cas


d’une redéfinition

• Si une méthode a le même nom qu’une méthode d’une classe


ascendante avec une signature différente, on est dans le cas
d’une surdéfinition (surcharge), quelque soient les droits
d’accès. La nouvelle méthode est utilisable par la classe
dérivée et ses descendantes 43
11. Duplication des champs
 Une classe dérivée peut définir un champ portant le même nom qu’un
attribut d’une classe ascendante. Le nouveau attribut s’ajoute à l’ancien.
Les deux attributs peuvent être utilisés en utilisant le mot clé super pour
désigner l’attribut de la classe ascendante
class A
{public int n;
a.n designe int n de la
…..}
classe A et b.n designe
Class B extends A
float n de la classe B
{public float n;
Il n’y a pas de redéfinition
public void f () {
du champs n comme il y
n=5.25f; super.n=3;
a redéfinition de
}}
méthode, mais création
A a; B b;
d’un nouveau champs qui
a.n=5;
s’ajoute a l’ancien.
b.n=3.5f;
44
LOGO

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.

 Le polymorphisme en Java, se traduit par :


• La compatibilité entre un type dérivée et un type ascendant.
• La ligature dynamique des méthodes, dans le sens où il
permet d’obtenir le comportement adapté à chaque type
d’objet, sans avoir besoin de tester sa nature de quelque façon
que ce soit.

 Le polymorphisme se base sur cette affirmation : un objet a


comme type non seulement sa classe mais aussi n’importe
quelle classe dérivée.
46
1. Le polymorphisme (2): Concept

Exemple: créer un tableau d’objets, les uns étant de type


Point et les autres de type PointCol et appeler la méthode
afficher(). Chaque objet réagira selon son type. Les objets
points colorés se sont aussi des points et peuvent donc être
traités comme des points. Mais, les objets points ne sont
pas des points colorés et ne peuvent être traités comme des
points colorés. La réciproque est fausse.

47
2. Les bases du polymorphisme (1)
Soient les classes Point et PointCol suivantes:

class Point { class PointCol extends Point {


private double x; private String couleur;
private double y;
Public Point (double x, double y)
Public PointCol (double x, double y,
{
String couleur) {
this.x = absc;
this.y = ord; super(x,y);
} this.couleur = couleur;
public void afficher() }
{ public void afficher() {
System.out.println("je suis un point de
super.afficher();
coordonnées:"+x+" "+y);
} System.out.println("couleur:" + couleur);
} }

48
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é
49
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).
50
2. Les bases du polymorphisme (4)

En résumé:

Le polymorphisme en java se traduit par :

• La compatibilité par affectation entre un


type classe et un type ascendant

• La ligature dynamique des méthodes

51
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
52
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

a référence un objet de type A // méthode f de A


a référence un objet de type B // méthode f de A
a référence un objet de type C // méthode f de C
a référence un objet de type D // méthode f de D
a référence un objet de type E // méthode f de A
a référence un objet de type F // méthode f de C
53
4. Polymorphisme, redéfinition et surcharge
(1)
class A
{
public void f(float x) {…}
}
class B extends A
{
public void f(float x) {…} //redéfinition de f de
public void f (int n) {…} //surcharge(surdéfiniton)de f pour A et B
…….
}
A a = new A(); B b = new B(); int n;

a.f(n); appelle f (float) de A


b.f(n); appelle f (int) de B
a = b; a contient une référence vers un objet de type B
a.f(n);
appelle f(float) de B

54
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.

Donc, malgré la ligature dynamique, le polymorphisme se fonde sur une


signature et un type de retour définis à la compilation ( et qui ne seront pas
remis en questions lors de l’exécution)

55
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.

56
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 »

57
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 »
}}
58
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;

Util.f(n, b); //sans conversion: Appel de f(int, B)


Util.f(x, a); //sans conversion: Appel de f(float,A)
Util.f(n, a); //conversion de n en float: Appel de f(float, A)
Util.f(x, b); //conversion de b en A: Appel de f(float, A)

59
5. Conversion des arguments effectifs: cas
d’arguments de type objet (4)
Cas 3.Méthode surdéfinie (Exemple moins trivial)
class A {…….}
class B extends A {….…}
class Util
{
static void f(int p, A a) {….}
static void f(float x, B b){….}
}

A a = new A(); B b = new B(); int n; float x;
Util.f(n, a); //sans conversion: Appel de f(int, A)
Util.f(x, b); //sans conversion: Appel de f(float, B)
Util.f(n, b); //Erreur de compilation: Ambiguité car deux
possibilités existent
Util.f(x, a); //Erreur de compilation car aucune méthode ne
convient , impossible de convertir A en B ni
float en int
60
6. Les règles de polymorphisme en java
L’abus des possibilités de redéfinition et surdéfinition peuvent conduire
à des situations complexes( comme on a pu le voir), voici un
récapitulatif des différentes règles:
❖ Compatibilité. Il existe une conversion implicite d’une référence à
un objet de classe C en une référence à un objet d’une classe
ascendante (aussi bien dans les affectations que dans les
arguments effectifs de méthodes)
❖ Ligature dynamique. Dans un appel de la forme x.f(…) où x est
supposé de type C, le choix de f est déterminé de la manière
suivante:
▪ A la compilation: On détermine dans la classe C ou ses ascendante la
signature de la meilleure méthode f convenant à l’appel, ce qui définit
également le type de retour.
▪ A l’exécution: On recherche la méthode f de signature et de type de
retour voulus, à partir de la classe correspondant au type effectif de
l’objet référencé par x ( Il peut être de type T ou descendant). Si cette
classe ne comporte pas de type approprié, on remonte dans la
hiérarchie jusqu’à en trouver une. 61
7. Conversion explicite de référence (1)
Il n’est pas possible d’affecter à une référence à un objet de type T , une
référence à un objet d’un type ascendant.

Exemple:
class Point{…}
class PointCol extends Point {…}

PointCol pc;
pc = new Point (…)// erreur de compilation

Considérons maintenant cette situation


Point p; PointCol pc1, pc2;
pc1 = new PointCol (…);

p= pc1; // p contient la référence à un objet de type PoinCol

pc2 = p; // Erreur en compilation même si p contient une référence à un
objet de type PoinCol 62
7. Conversion explicite de référence (2)
Il faudrait faire une conversion en utilisant l’opérateur de cast comme pour les
types primitifs.
Point p; PointCol pc1, pc2;
pc1 = new pointCol (…);

p= pc1; // p contient la référence à un objet de type PoinCol

pc2 = (Pointcol) p; // accepté par le compilateur mais sera vérifié à
// l’exécution. Si p ne contient pas une référence à
// un objet de type PointCol ou dérivé, l’exécution
//sera arrêtée.

Remarque: Pour s’assurer qu’un objet est bien d’une classe donnée, il suffit
d’utiliser l’opérateur instanceof

Exemple: p instanceof Point retourne true si p est effectivement de type


Point.

If ( p instanceof Point) System.out.println (" je suis un point ");


63
8. La super-classe Object(1)

 Nous avons vu deux types de classes jusqu’ici: les classes


simples et les classes dérivées.
 Il existe une classe dont dérivent implicitement toute classe
simple qui est la clase Object. C’est le sommet de la hiérarchie
de toutes les classes java.

 Si nous définissons une classe Point


class Point
{…
}
Tout se passe comme si on avait écrit
class Point extends Object
{…
}

64
8. La super-classe Object (2)

public class Object {


public Object () {...} //Constructeur
protected Object clone(){...}
public boolean equals(Object o){...}
protected void finalize(){...}
public Class getClass(){...}
public int hashCode(){...}
public String toString(){...}
// méthodes utilisées dans la gestion des threads
public void notify(){...}
public void notifyAll(){...}
public void wait(){...}
public void wait(long timeout){...}
public void wait(long timeout, int nanos){...} }

65
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.
66
10. Utilisation de méthodes de la classe Object

Point p1 = new Point(1,2);


Point p2 = new Point(1,2);

p1.equals(p2) retourne la valeur …?

67
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 ; }

public boolean equals (Object pp)


{ if (pp == null) {return false;}
if (pp == this) {return true;}
if (! this.getClass().equals(pp.getClass())){return false;}
Point p = (Point) pp ;
return ((this.x == p.x) & (this.y == p.y)) ;
}
68
12. Utilisation d’une référence de type Object

Etant données les possibilités offertes par le polymorphisme, une


variable de type Object peut être utilisée pour référencer un objet
de type quelconque. Ceci peut être utilisé pour manipuler des objet
dont on ne connait pas le type exact au moment où on l’utilise.

Exemple:
Point p = new Point();
Object o;

o= p;

o.deplacer (); // erreur de compilation

((Point ) o). deplacer (); //OK

69
13. Les membres protégés (1)

Nous avons vu les droits d’accès publique ( avec le mot clé


public) et privé (avec le mot clé private).
Il existe un troisième droit d’accès dit protégé (en utilisant
le mot clé protected).

Un membre déclaré protected est accessible à ses classes


dérivées ainsi qu’aux classes de même paquetage.

(Il existe un quatrième droit d’accès qu’on verra plus tard)

70
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

71
14. Héritage et tableaux

Même si nous considérons les tableaux comme


étant des objets, il n’est pas possible de définir
leur classe et par conséquent ils ne bénéficient
que d’une partie des propriétés des objets.
1. Un tableau peut être considéré comme
appartenant à une classe dérivées d’Object
Object o;
o = new int[5]; // correct
o = new float [3]; // correct

2. Il n’est pas possible de dériver une classe d’un


tableau
Class Test extends int []; // erreur

72
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

Mais cette propriété ne peut pas s’appliquer aux types


primitifs
int ti [], float tf[]; ….
ti = tf; // erreur ( évident car float n’est pas
compatible avec int)
tf = ti; // erreur bien que int soit compatible avec float 73
16. Classes et méthodes finales
▪ Lorsque le mot clé final est appliqué à une variable ou à des
champs d’une classe, il interdit la modification de leur valeur.

final int n = 23;



n=n+5; // erreur
▪ Le mot clé final peut s’appliquer à une classe ou à une méthode
mais avec une signification totalement différente.

▪ Une méthode déclarée finale ne peut pas être redéfinie dans une
classe dérivée.

▪ Une classe déclarée finale ne peut pas être dérivée

74
Références bibliographiques

❖ Hugues Bersini, La programmation orientée objet,


ÉDITIONS EYROLLES, 2009
❖ N Bousbia et S SadeG, Programmation Orienté Objet,
Ecole nationale Supérieur d’Informatique ESI,
2013/2014.
❖ http://fr.slideshare.net/useriuo/eyrolles-sinitier-
alaprogrammationavecdesexemplesencccjavaetphp
❖ Claude Delannoy, « Programmer en Java », Eyrolles
http://java.sun.com/docs/books/jls/
Exercice 1: Quels résultats fournit le
programme suivant?
class A {
public void affiche() { System.out.print("Je suis un A "); } }
class B extends A { }
class C extends A {
public void affiche() { System.out.print("Je suis un C "); } }
class D extends C {
public void affiche() { System.out.print("Je suis un D "); } }
class E extends B { }
class F extends C { }
class Poly {
public static void main(String arg[]) {
A a = new A(); a.affiche(); System.out.println(); B b = new B(); b.affiche(); a = b;
a.affiche(); System.out.println(); C c = new C(); c.affiche(); a = c; a.affiche();
System.out.println(); D d = new D(); d.affiche(); a = d; a.affiche(); c = d; c.affiche();
System.out.println(); E e = new E(); e.affiche(); a = e; a.affiche(); b = e; b.affiche();
System.out.println(); F f = new F(); f.affiche(); a = f; a.affiche(); c = f; c.affiche();
}}
76
Exercice 2: On considère les en-tête de
méthodes suivantes :
1. int f(int n, char c)
2. void f()
3. int f(int n)
4. int f(char c, int n)
5. int f(int n, char c)
6. void f(int n, char c)
7. int f(int n, char c, float x)
Quelles combinaisons de méthodes peuvent être définies
simultanément dans une même classe ?
Solution:
-1, 2, 3, 4 et 7.
- 2, 3, 4, 5 et 7.
- 2, 3, 4, 6 et 7.
77
Exercice 3: En considérant le graphe de classes suivant,
correspondant à une hiérarchie d’héritage :
1. Dans quelle(s) classe(s) aurait-il plus de sens d’avoir des membres
avec le modificateur protected ? Quelle(s) est (sont) la (les) classe(s) A
qui peut (peuvent) accéder directement aux membres protected ?
2. Soit les déclarations suivante: A O1 = new A(); A O2= new B();
B C
B O3= new B() ; C O4= new C(); D O5= new D(); A O6= new E();
Indiquez, pour chacune des instructions suivantes, si elles sont
correctes ou non, et dans ce cas, quel type d'erreur produisent-elles
(et est ce une erreur de compilation, ou d'exécution) et comment peut D E
on faire pour qu'elles ne produisent plus d'erreur? (les instructions ne
sont pas exécutés en séquence)
Instruction fonctionnement
1 O2 = O1 ;
2 O3 = O2;
3 O4 = O3;
4 O5 =(D)O4;
5 O1=O5;
6 O4=O6; 78
Exercice 3: Solution

1. Les classes A et C c’est les seules classes de l’hiérarchie qui ont des sous
classes donc il serait logique pour eux d'avoir des membres protégé . Les
classe B, C, D, E peuvent accéder aux membres protected de A et les classes
D et E peuvent accéder aux membres protected de C.

Instruction fonctionnement

1 O2 = O1 ; ok
2 O3 = O2; Erreur à la compilation, impossible de convertir de A à B, correction :
O3 =(B)O2; Correcte à l’exécution

3 O4 = O3; Erreur à la compilation, impossible de convertir de B à C

4 O5 =(D)O4; Erreur à l’exécution, C ne peut pas être converti en D

5 O1=O5; ok

6 O4=O6; Erreur à la compilation, impossible de convertir de A à C, correction :


O4 =(C)O6; Correcte à l’exécution
79

Vous aimerez peut-être aussi