Vous êtes sur la page 1sur 40

Institut National des Télécommunication et des Technologies de l'Information et de

la Communication INT-TIC d'Oran Algérie

LE LANGAGE JAVA

Chapitre 4 : Héritage et Polymorphisme


en JAVA

R. HACHEMI G. MERED
HÉRITAGE EN JAVA
 Idée : Organiser les classes de manière hiérarchique.
 La relation d’héritage est unidirectionelle : si une classe B
hérite d’une classe A, il est évident que la classe A n’hérite pas
de la classe B. B est dite sous classe de A.

Notation : class B extends A


{
<contenu de la classe>
}
 Redéfinition : il est possible de redéfinir une méthode dans la
sous classe.
 Remarque : en JAVA, toutes les classes sont dérivées de la
classe Object.
HÉRITAGE EN JAVA
 Exemple : Classes Ville et Capitale

class Ville {
private String nom;
Attributs
protected int nbHab;

public Ville(String leNom){


nom = leNom.toUpperCase(); Constructeur
nbHab = -1;
}

HÉRITAGE EN JAVA
 Exemple : Classes Ville et Capitale

public Ville(String leNom, int leNbHab){
nom = leNom.toUpperCase();
if (leNbHab < 0){
System.out.println(« Un nombre
d’habitant doit être positif !");
nbHab = -1;
} else
nbHab = leNbHab;
}

HÉRITAGE EN JAVA
 Exemple : Classes Ville et Capitale

public String getNom() { return nom; }
public int getNbHab() { return nbHab; }
public void setNbHab(int nvNbHab) {
if (nvNbHab < 0)
System.out.println(« Un nombre
d’habitant doit être positif . La
modification n’est prise en
compte !");
else nbHab = nvNbHab;
}

HÉRITAGE EN JAVA
 Exemple : Classes Ville et Capitale

public String presentation() {
String presente;
presente = "Ville " + nom + "nombre d’habitants " ;
if (nbHab == -1)
presente = presente + "inconnu" ; else
presente = presente + " = " + nbHab;

return presente;
}
} // FIN DE LA CLASSE VILLE
HÉRITAGE EN JAVA
 Exemple : Classes Ville et Capitale

class Capitale extends Ville {


private String pays; Attribut
public Capitale(String leNom, String lePays){
super(leNom);
Constructeurs

pays = lePays.toUpperCase();
}
public Capitale(String leNom, String lePays, int leNbHab){
super(leNom, leNbHab);
pays = lePays.toUpperCase();
}

HÉRITAGE EN JAVA
 Exemple : Classes Ville et Capitale

public String getPays() { return pays; }
public void setPays(String nomPays) {
pays = nomPays;
}
public String presentation() {
Redéfinition

String presente = super.presentation();


presente = presente + " Capitale de " + pays;
return presente;
}
} // FIN DE LA CLASSE CAPITALE
HÉRITAGE EN JAVA
 Exemple : Classes Ville et Capitale
public class TestVille {
public static void main(String args[ ]) {
Ville v1 = new Ville("Oran", 1500000);
Ville v2 = new Ville("Constantine");
Capitale c1 = new Capitale("Alger", "Algerie", 2000000);
Capitale c2 = new Capitale(« Dakar", "Senegal");
Syetem.out.println(v1.presentation());
Syetem.out.println(v2.presentation());
Syetem.out.println(c1.presentation());
Syetem.out.println(c2.presentation());
}
} // FIN DE LA CLASSE TESTVILLE
HÉRITAGE EN JAVA
 Exemple : Classes Ville et Capitale

Le test donne le résultat suivant :

Ville ORAN nombre d’habitants = 1500000


Ville CONSTANTINE nombre d’habitants inconnu
Ville ALGER nombre d’habitants 2000000 Capitale de ALGERIE
Ville DAKAR nombre d’habitants inconnu Capitale de SENEGAL

Remarque : les sous-classes n’ont pas un accès direct aux membres


privés de leurs classe mères comme le montre cet exemple.
TRANSTYPAGE
 Transtypage (conversion de type ou cast en anglais) consiste
à modifier le type d’une variable ou d’une expression.
 Lors d’une affectation

 Lors d’un passage de paramère effectif

1. Transtypage des type primitifs

Transtypage implicite Transtypage explicite

 traité automatique-ment  Clairement exprimé par


par le compila-teur le programmeur
TRANSTYPAGE
1. Transtypage des types primitifs (suite):

Le Transtypage implicite est traité automatique-ment par le


compilateur, à condition que le type cible ait un plus grand
domaine par rapport au type d’origine (gain de precision).

int a = 2; void fct(short p){


double b = a; …
}
byte x = 3;
fct(x);
TRANSTYPAGE
1. Transtypage des types primitifs (suite):

Si le domaine de valeurs du type cible est plus restreint, il faut


réaliser un Transtypage exmplicite (perte de precision).

int n = 3; float f;
f = n; // f vaut 3.0
f = f + 1; // conversion de 1 en 1.0 et somme : f vaut 4.0
n = (int) f; // n vaut 4
f = f + 1.5; // f vaut maintenant 5.5
n = (int) f; // 5.5 est arrondi en 5 : n vaut 5
TRANSTYPAGE
2. Transtypage des objets (des références des objets) :

Il est possible de convertir un objet d’une classe en un objet


d’une autre classe si les classes ont un lien d’héritage (en
effet, ce sont les références aux objets qui sont transtypées).

classe Fille classe Mère est implicite


classe Mère classe Fille est explicite

Dans le 2ème cas, le transtypage doit être explicite, et il n’est


pas toujours possible.
TRANSTYPAGE
2. Transtypage des objets (des références des objets) :

Exemple de Transtypage implicite

Une Capitale est une Ville

Ville v;
Capitale c = new Capitale("Alger", "Algerie");
v = c;

La référence « v » est alors utilisée pour désigner un


objet de type Capitale. L’objet désigné par « c », qui
est de type Capitale est donc transtypé en Ville.
TRANSTYPAGE
2. Transtypage des objets (des références des objets) :

Exemple de Transtypage implicite

Conséquence : On ne pourra pas utiliser « v » pour


appeler une méthode spécifique de la classe Capitale.
Il faudrait pour cela effectuer un transtypage
explicite de « v » en Capitale.

Remarque : contrairement au cas des types primitifs,


le transtypage implicite des objets entraine une perte de
précision.
TRANSTYPAGE
2. Transtypage des objets (des références des objets) :

Exemple de Transtypage explicite

Une Ville n’est pas forcément une Capitale

String lePays;
lePays = (Capitale) v.getPays();

L’instruction lePays = v.getPays() aurait provoqué une


erreur car getPays() n’est pas une méthode de la classe Ville.
TRANSTYPAGE
2. Transtypage des objets (des références des objets) :

Exemple de Transtypage explicite

Remarque : le transtypage explicite n’est pas toujours


possible. Il faut que l’objet soit effectivement du type dans lequel
on transtype la référence.

Dans cet exemple, le transtypage de « v » en Capitale était


possible car l’objet désigné est effectivement
Capitale.
POLYMORPHISME
Question : et si on voulait invoquer la méthode presentation() avec la
référence « v »? Quelle implémentation s’exécuterait alors ?

 Celle de Ville qui donne :


Ville Alger nombre d’habitant inconnu
 Ou celle de Capitale qui donne :
Ville Alger nombre d’habitant inconnu Capitale de Algerie

Réponse : Celle de Capitale, même si « v » est de type Ville.

presentation() est une méthode polymorphe.


POLYMORPHISME
Le choix de l’implémentation d’une méthode polymorphe ne se fait
pas en fonction du type déclaré de la référence à l’objet, mais en
fonction du type réel de l’objet.

Le choix se fait dynamiquement à l’exécution.

Exemple :

La Classe Vector permet de mémoriser une liste d’objets.

Vector maListe = new Vector();

Grace au mécanisme de transtypage implicite, un Vector peut contenir


des références à des objets de n’importe quelle classe (la classe Object
étant la classe mère de toute les classes).
POLYMORPHISME
Exemple (suite) :

Vector maListe = new Vector();

Ville v1 = new Ville("Oran", 1500000);


Ville v2 = new Ville("Bechar");
Capitale c1 = new Capitale("Alger", "Algerie");

maListe.addElement(v1); // transtypage implicite de Ville


maListe.addElement(v2); // et de Capitale en Object
maListe.addElement(c1);
POLYMORPHISME
Exemple (suite) :

Mais ensuite, pour utiliser les éléments contenus dans Vector et leurs
méthodes propres, il faut indiquer la classe correspondante par un
transtypage explicite.

maListe.elementAt(0).presentation()

Cette instruction provoquerait une erreur, car la méthode elementAt()


renvoie un objet de la classe Object (et non de la classe Ville). Il faut
donc transtyper (explicitement) l’objet renvoyé en Ville :

((Ville)(maListe.elementAt(0))).presentation();
POLYMORPHISME
Exemple (suite) :

Le polymorphisme permet à ce stade d’utiliser une référence de la


classe Ville pour désigner un objet de la classe Capitale, et d’invoquer
son implémentation de la méthode presentation().

for ( int i = 0; i < 3; i++){


((Ville)(maListe.elementAt(i))).presentation();
}

Le système saura alors quelle implémentation de la méthode


présentation() exécuter en fonction de la classe réelle de l’objet.
POLYMORPHISME
Exemple (suite) :

Sans polymorphisme, la méthode aurait dû s’écrire :

for ( int i = 0; i < 3; i++){


if (maListe.elementAt(i) instanceof Ville) {
((Ville)(maListe.elementAt(i))).presentation();
}
else if (maListe.elementAt(i) instanceof Capitale) {
((Capitale)(maListe.elementAt(i))).presentation();
}
}
POLYMORPHISME
Exemple 2 (mauvais usage du polymorphisme) :

class M { class F extends M {


M() { private int i;
m();
} F(int i) {
void m() { … } super();
} this.i = i;
}
F f = new F(5); void m() {
System.out.println(
affichera : "i de F = " + i )
}
i de F = 0 }
POLYMORPHISME
Exemple 2 (mauvais usage du polymorphisme) :

En effet, l’appel au constructeur de la classe mère est effectué avant


que les variables d’instance ne soient initialisées dans le constructeur
de la classe fille.

Dans cet exemple, le constructeur de la classe mère comporte un appel


à une méthode (m) redéfinie dans la classe fille. Cette méthode ne
pourra utiliser les bonnes valeurs pour les variables d’instance
initialisées dans le constructeur de la classe fille.

Conseil : Eviter l’appel d’une méthode polymorphe dans un


constructeur.
POLYMORPHISME
Explication du fonctionnement :

Analyse statique à la compilation : Java essaie de détecter le plus


possible d’erreur à la compilation (une erreur est souvent plus coûteuse
si elle est détectée lors de l’exécution).

Le typage statique doit garantir dès la compilation l’existence de la


méthode appelée : la classe déclarée de l’objet doit posséder cette
méthode (son implémentation n’est prise en compte qu’au moment de
l’exécution).
POLYMORPHISME
Explication du fonctionnement :

Mécanisme de la liaison retardée (last bending) :


Soit C la classe réelle d’un objet « o » à qui on envoie un message «
o.m() ».
Si le code source de la classe C contient la définition (ou la
redéfinition) d’une méthode m(), c’est cette méthode qui est exécutée.
Sinon, la recherche de la méthode m() se poursuit dans la classe mère
de C, puis dans la classe mère de cette classe mère, et ainsi de suite,
jusqu’à trouver la définition d’une méthode m() qui est alors exécutée.
INTERFACE
Au même titre qu’une classe, une interface joue le rôle d’un type,
mais abstrait.

Une interface décrit un ensemble de signatures de méthodes, sans


implémentation, qui doivent être implémentées dans toutes les classes
implémentant l’interface.

inteface NomInterface {
methode1();
methode2();
class A implements NomInterface{


}
}
INTERFACE
class A implements NomInterface { … }

2 cas se présentent :

 soit la classe A implémente toutes les méthodes de l’interface


NomInterface.

 soit la classe A doit être déclarée abstraite (mot clé abstract); les
méthodes non implémentées le seront dans les classes fille de A.
INTERFACE

Une interface possède les caractéristiques suivantes :

elle contient des signatures de méthodes;


elle n’est pas instanciable;
elle ne peut pas contenir de variables;
une interface peut hériter d’une autre interface (avec le mot-clé
extends);
 elle n’appartient pas à l’arborescence des classes.
une classe, abstraite ou non, peut implémenter une ou plusieurs
interfaces (séparés par des virgules).
INTERFACE
Intérêt des interfaces :

Une interface peut servir à déclarer :

 une variable;
 un paramètre;
 une valeur de retour;
 un type de base d’un tableau;
…

L’exemple suivant montre comment utiliser une interface pour


déclarer un paramètre.
INTERFACE
Intérêt des interfaces :

Exemple 1 :

On veut définir une méthode qui vérifie si un tableau est croissant. On


veut que cette méthode puisse s’appliquer sur différents types de
tableaux (être le plus générique possible).

Ces différents types doivent avoir une propriété commune : définir une
relation d’ordre, autrement dit, ils doivent être comparables.
INTERFACE
Intérêt des interfaces :

Exemple 1 :

Pour cela, Java propose une interface, appelée Comparable, qui


propose une seule méthode (prototype) appelée compareTo. Cette
méthode, représentant la relation d’ordre, doit être implémentée par
toute classe implémentant l’interface Comparable.

Interface Coparable { // cette méthode est sensée


int compareTo(Object o); // renvoyer 3 valeurs possibles :
} // -1, 0 ou +1.
INTERFACE
Intérêt des interfaces :

Exemple 1 :

Les classes implémentant cette interface posséderont donc une


propriété commune (la méthode compareTo() ) avec des
implémentations différentes.

Notre méthode (qui doit vérifier si un tableau est croissant) peut être
définie de telle sorte qu’elle puisse s’appliquer sur toutes ces classes
(le paramètre est un tableau de comparables) :
INTERFACE
Intérêt des interfaces :

Exemple 1 :
public static boolean croissant(Comparable[ ] t) {
for (int i = 0; i < t.length – 1; i++) {
if (t[i].compareTo(t[i+1]) == +1)
return false;
}
return true;
}
INTERFACE
Intérêt des interfaces :

Exemple 1 :

Pour vérifier la croissance du tableau, cette méthode fait appel à la


méthode compareTo(). Le comportement polymorphe de la JVM va
permettre, à l’exécution, de choisir l’implémentation adéquate de
comparteTo() (en fonction du paramètre effectif d’appel).

Remarque : dans Java, il existe des méthodes qui suivent le même


principe que notre méthode croissant(), comme la méthode sort() de la
classe Arrays ou celle de la classe Collections, qui permettent de trier
un tableau ou une collections.
INTERFACE
Intérêt des interfaces :

Exemple 2 :

La déclaration
Comparable v;
indique que la variable v peut référencer des objets de classes
différentes : les classes implémentant l’interface Comparable.

L’utilité du concept d’interface réside dans le regroupement de


plusieurs classes, implémentant un ensemble commun de méthodes,
sous un même type.

C’est aussi une manière pour pallier au problème de l’héritage


multiple (qui n’est pas permis en Java).
INTERFACE
Autres intérêts des interfaces :

 Faire du polymorphisme avec des objets dont les classes


n’appartiennent pas à la même hiérarchie d’héritage.

 Si le type d’un paramètre d’une méthode est une interface, cette


méthode peut s’appliquer à toutes les classes qui implémentent
l’interface, et pas seulement à toutes les sous-classes d’une certaine
classe.

 Une classe peut réaliser plusieurs services de différentes natures en


implémentant plusieurs interfaces.

 Favorisation de la réutilisation, puisqu’une interface peut être


implémentée par de nombreuses classes.
INTERFACE
Inconvénients des interfaces :

 Une interface implémentée par de nombreuse classes est


difficilement modifiable. En effet, l’ajout d’une méthode à cette
interface rendra non compatibles toutes les classes qui implémentaient
l’ancienne version de l’interface.

 Les classes abstraites ne provoque pas ce genre de problèmes : on


peut lui rajouter une méthode non abstraite (les sous classes hériteront
de cette méthode).

Vous aimerez peut-être aussi