Vous êtes sur la page 1sur 19

Programmation orientée objet Mme Eya cheikh

Chapitre 4 : Héritage

1
Programmation orientée objet Mme Eya cheikh

Introduction
L’héritage constitue l’une des bases de la programmation orientée objet. En particulier il est à
la base des possibilités de réutilisation de composants logiciels.
Prenons ce cas : une application a besoin de services dont une partie seulement est proposée par
une classe déjà définie (classe dont on ne possède pas nécessairement la source) sans devoir
réécrire le code.
La solution en POO c’est l’héritage c’est à dire définir une nouvelle classe à partir de la classe
déjà existante.

I. L’héritage
1.1 Définition
L’héritage permet de définir de nouvelles classes dites dérivées ou filles ou sous-classes à partir
d’une ou de plusieurs classes existantes dites de base ou mères ou super-classes.
La classe dérivée héritera des potentialités de la classe de base tout en lui ajoutant de nouvelles
possibilités.
Donc même si une classe ne répond pas totalement à nos besoins, nous pouvons profiter de cette
classe et ceci en créant une nouvelle classe qui va hériter de la classe existante et lui ajouter
d’autres propriétés et d’autres opérations.

1.2 Types de relation entre les classes


Deux types de relations peuvent être envisagés entre deux classes :
 La relation « est un »
 La relation « concerne un »
La relation d’héritage peut être appliquée lorsque « la relation est un » peut être appliquée
entre deux classes.
Par exemple, pour les trois classes Personne, Client, Commande on a les relations suivantes :
- Une Commande concerne un Client
- Un Client est une Personne

2
Programmation orientée objet Mme Eya cheikh

La représentation schématique de l’héritage entre deux classes est la suivante :

Classe de base

Classe dérivée

A l’intérieur de cette nouvelle classe (classe dérivée) on peut :


- Utiliser des attributs hérités de la classe de base (à condition bien sûr que leur
visibilité le permette) ;
- Ajouter de nouveaux attributs ;
- Masquer un attribut hérité en le déclarant avec le même nom que celui utilisé dans la
classe de base ;
- Utiliser une méthode héritée sous réserve que sa visibilité le permette ;
- Substituer une méthode héritée en la déclarant à l’identique (même signature) ;
- Surcharger une méthode héritée en la créant avec une signature différente ;
- Ajouter une nouvelle méthode ;
- Ajouter un ou plusieurs constructeurs ;

1.2 Syntaxe
La syntaxe de l’héritage est la suivante :
// La Super-classe // La Sous-classe
class A class B extends A
{// membres de la classe A {// membres de la classe B
} }
Exemple
Prenons l’exemple de la classe Client qui hérite de la classe Personne et à laquelle est ajouté
l’attribut type et les accesseurs correspondants.

Personne

Client

3
Programmation orientée objet Mme Eya cheikh

class Personne {
…………..
}

class Client extends Personne {


private String type;
public String getType() {
return type;
}

public void setType(String t) {


type = t;
}
}

Remarque
Une classe fille dérive d'une unique classe mère, l'héritage multiple n'étant pas supporté par le
langage Java. On verra par la suite un moyen de simuler l’héritage multiple par le concept
d’interface.

II. Constructeur de la sous-classe


2.1 Appel du constructeur
Un constructeur ne peut être hérité en aucun cas. Pour pouvoir utiliser dans la classe fille un
constructeur particulier de la classe mère il faut le spécifier explicitement. Par contre, des règles
existent sur l'utilisation des constructeurs de la classe mère dans les constructeurs d'une classe
fille quelconque.
Avant de voir ces règles en détail, il faut préciser que le mot clé super sert à accéder aux
membres de la classe mère au niveau de la classe considérée.
 Règle 1 : Si, la première instruction du constructeur de la classe dérivée n’est pas un appel
explicite d’un constructeur de la classe de base (utilisation de super(...)), le constructeur par
défaut de la classe de base est appelé implicitement et doit être défini dans la classe mère.

4
Programmation orientée objet Mme Eya cheikh

 Règle 2 : Si on invoque super( ), cela signifie que le constructeur en cours d'exécution passe
la main au constructeur de la classe mère pour commencer à initialiser les attributs définis dans
cette dernière. Ensuite le premier constructeur continue son exécution.
 Règle 3 : Si on invoque this(), le constructeur considéré passe la main à un autre constructeur
de la classe considérée. Encore une fois, cela doit être la première instruction du bloc.

3.2 Exemples
fichier "Classe1.java" fichier "Classe2.java"
class Classe1 {
Classe1(){ class Classe2 extends Classe1 {
System.out.println("Classe1"); Classe2(){
} super(5);
System.out.println("Classe2"); }
Classe1(int val){ Classe2(int val){
this(); System.out.println(val); }}
System.out.println(val); }}
Exemple de création d'objet Résultats
new Classe1(); Classe1
Classe1
new Classe1(3);
3
Classe1
new Classe2(); 5
Classe2
Classe1
new Classe2(2);
2

2.3 Enchaînement des constructeurs


La classe Object est la mère de toutes les classes : toute classe est dérivée directement ou non
de la classe Object. Pour tout objet instancié, le constructeur de sa classe est invoqué, lequel à

5
Programmation orientée objet Mme Eya cheikh

son tour, invoque le constructeur de sa classe de base et ainsi de suite. Cette cascade d’appels
s’arrête évidemment lorsqu’on atteint le constructeur de la classe Object.

2.4 Exemple complet


class Date {
protected int mois;
protected int jour;
protected int annee;

public Date(int j, int m, int a) {


jour = j;
mois = m;
annee = a;}
public void set_Date(int j, int m, int a) {
mois = m;
jour = j;
annee = a;}
public void afficher() {
System.out.println(jour + mois + annee);}
}
class DateAnniversaire extends Date {
private String nom;
private String prenom;
public DateAnniversaire(int j, int m, int a, String n, String p) {
super(j, m, a);
nom = n;
prenom = p;}
public void set_DateAnniversaire(int j, int m, int a, String n, String p) {
super.set_Date(j, m, a);
nom = n;
prenom = p;}

6
Programmation orientée objet Mme Eya cheikh

public void afficher_Anniversaire() {


System.out.print(prenom + " " + nom + " est ne(e) le ");
super.afficher();
// ou bien :
// System.out.println(prenom+" "+
// nom+" est ne(e) le "+super.jour+"/"+super.mois+ "/"+super.annee)}}
class TestDate {
public static void main(String[] arg) {
DateAnniversaire d = new DateAnniversaire(0, 0, 0, "", "");
d.set_DateAnniversaire(10, 3, 1980, "Ltaiif", "Khaled");
// ou bien directement
// DateAnniversaire d = new DateAnniversaire(10, 3, 1980, "Ltaiif",
// "Khaled");
d.afficher_Anniversaire();}
}

III. Redéfinition
3.1 Redéfinition des attributs
Les attributs déclarés dans la classe dérivée sont toujours des attributs supplémentaires.
Si l’on définit un attribut ayant le même nom qu’un attribut de la classe de base, il existera alors
deux attributs de même nom. Le nom de l’attribut désignera celui déclaré dans la classe dérivée.
Pour avoir accès à celui de la classe de base, il faudra changer le type de la référence pointant
sur l’objet, ou utiliser super.
Exemple
class A {
public int i;
}
class B extends A {
public int i;
public void uneMethode() {
i = 0; // attribut défini dans la classe B

7
Programmation orientée objet Mme Eya cheikh

this.i = 0; // attribut défini dans B


super.i = 1; // attribut défini dans A
((A) this).i = 1; // attribut défini dans A
……… }
}
class C extends B {
public int i;
public void uneMethode() {
i = 0; // attribut défini dans la classe C
this.i = 0; // attribut défini dans C
super.i = 1; // attribut défini dans B
((B) this).i = 1; // attribut défini dans B
((A) this).i = 1; // attribut défini dans A
}
}
Remarque
L’instruction suivante est incorrecte ! super.super.i=1 ;
De plus, comme l’utilisation du mot-clé this, le mot clé super ne peut pas être utilisé dans les
méthodes qualifiées de static.

3.2 Redéfinition des méthodes


On n’est bien sur pas tenu de déclarer de nouveaux attributs dans une classe dérivée, il se peut
que seuls les comportements (méthodes) changent avec de nouvelles méthodes ou des méthodes
redéfinies.
La redéfinition d’une méthode consiste à fournir une implémentation différente de la méthode
de même signature fournie par la classe mère.
Exemple
class point {
private int x, y;
public point(int a, int b) {
x = a;

8
Programmation orientée objet Mme Eya cheikh

y = b;
}
void affiche() {
System.out.print("(" + x + "," + y + ")");
}
}
class pixel extends point {
private String couleur;
public pixel(int a, int b, String c) {
super(a, b);
couleur = c;
}
void affiche() {
System.out.print("[");
super.affiche();
System.out.print(":" + couleur+"]");
}
public static void main(String[] argv) {
point p = new point(2, 3);
pixel px = new pixel(4, 5, "rouge");
p.affiche();
System.out.println();
px.affiche();
}
}
Exécution
(2,3)
[(4,5):rouge]
Remarques
 Pour avoir accès à une méthode redéfinie de la classe de base, il faudra utiliser le mot
clé super.

9
Programmation orientée objet Mme Eya cheikh

 Une méthode static peut aussi être redéfinie par une autre méthode static (mais pas
par une méthode non static).

IV. Méthodes et classes finales


5.1 Les méthodes finales
Une méthode finale est une méthode dont la redéfinition est interdite aux classes
dérivées. Elle est déclarée avec le mot clé final.
[public/protected] final <Nom_Méthode>( )
{………}

5.2 Les classes finales


Il est possible d’empêcher l’héritage de classes. Pour cela on ajoute le modificateur
d’accès final qui indique que la classe ne peut être dérivée. Une classe finale ne peut
pas avoir des classes dérivées, toutes ses méthodes sont alors implicitement finales.
[public/protected] final class <Nom_Classe>( )
{………
}
Il y a plusieurs classes finales du langage comme par exemple la classe String, dont
voici la déclaration extraite de la documentation Java :
public final class String extends Object…….
{
……………
}

10
Programmation orientée objet Mme Eya cheikh

5.3 Intérêt des classes et des méthodes finales


La déclaration d’une classe ou d’une méthode de type final permet une gestion
statique, d’ou un gain en temps d’exécution. En effet, Le compilateur ne peut pas remplacer
une méthode simple par du code en ligne (inline), car il est toujours possible qu’une classe
dérivée surcharge le code de la méthode. Par contre, le compilateur peut remplacer une
méthode final par son code car celle-ci ne pourra pas être surchargée.
D’un autre coté, une définition statique d’une méthode permet un contrôle plus sûre de son
exécution.

V. La classe Object
6.1 Définition
La classe Object est la racine de l'ensemble de la hiérarchie de classes Java. Elle est directement
ou indirectement présente dans la hiérarchie de toute classe d’une application. Les méthodes
définies dans la classe Object sont donc disponibles pour n’importe quelle classe.

6.2 Les méthodes de la classe Object


L’inconvénient de ces méthodes est que leur fonctionnement n’est pas adapté aux différentes
classes de l’application. Elles ont donc souvent besoin d’être redéfinies dans les classes de
l’application pour pouvoir être utilisées efficacement. On va donc étudier en détail les plus
utilisées d’entre elles:
 Class getClass() renvoie des informations sous la forme d'un objet de la classe Class à partir
de laquelle l’objet a été crée. On peut par exemple obtenir le nom de la classe, les méthodes
disponibles, les champs, etc. Par mesure de sécurité, cette méthode ne peut pas être redéfinie.
Exemple
Voici une méthode affichant quelques informations sur la classe de l’objet qui lui est passé
en paramètre.

public static void infoClass(Object o) {

11
Programmation orientée objet Mme Eya cheikh

Class c;
c = o.getClass();
System.out.println(" Le nom de la classe : " + c.getName());
System.out.println(" Elle est dans le package : "
+ c.getPackage().getName());
System.out.println(" Elle hérite de la classe :"
+ c.getSuperclass().getName());
System.out.println(" Elle possède les attributs :");
for (int i = 0; i < c.getFields().length; i++) {
System.out.println("\t" + c.getFields()[i].getName());
System.out.println(" de type:"
+ c.getFields()[i].getType().getName());
}
System.out.println(" Elle possède les méthodes :");
for (int i = 0; i < c.getMethods().length; i++) {
System.out.println("\t" + c.getMethods()[i].getName());
}
}

class Test {
public static void main (String[] args) {
Client c1, c2;
c1 = new Client("n1", "p1", "tunis", "Particulier");
Client.infoClass(c1);}
}
Voici le résultat obtenu :
Le nom de la classe : Ex2.Client
Elle est dans le package : Ex2
Elle hérite de la classe :Ex2.Personne
Elle possède les attributs :

12
Programmation orientée objet Mme Eya cheikh

Nom
de type:java.lang.String
Prenom
de type:java.lang.String
Elle possède les méthodes :
equals
getType
infoClass
setType
getNom
getPrenom
getAdresse
setNom
setPrenom
setAdresse
init_Personne
afficher_homme
wait
wait
wait
toString
hashCode
getClass
notify
notifyAll

 public int hashCode() :


Elle renvoie un entier qui est le résultat d’un calcul qui a été fait sur les valeurs des attributs.
Donc deux instances qui ont les mêmes valeurs des attributs doivent avoir la même valeur
de hashCode(). Cette méthode est surtout utilisée par la méthode equals.
 public boolean equals(Object autreObjet) :

13
Programmation orientée objet Mme Eya cheikh

Elle retourne true si les 2 références autreObjet et this désignent le même objet. Ce sont au
fait les hash-code des deux objets qui sont comparés.
Exemple

public boolean equals(Object obj) {


Client c;
if (obj == null || obj.getClass() != this.getClass()) {
return false;
} else {c = (Client) obj;// vérification des critères d'égalité sur tous les attributs
if (c.getNom().equals(this.getNom()) &
c.getPrenom().equals(this.getPrenom()) &
c.getAdresse().equals(this.getAdresse())&
c.getType().equals(this.getType()))
{return true;
} else {
return false; }
}
}
}
class Test {public static void main(String[] args) {
Client c1, c2;
c1 = new Client("n1", "p1", "tunis", "Particulier");
c2 = new Client("n2", "p2", "bizerte", "Entreprise");
if (c1.equals(c2))
System.out.println("les deux clients sont identiques");
else
System.out.println("les deux clients sont différents");}}
Voici le résultat obtenu :
 les deux clients sont différents

 public String toString() :

14
Programmation orientée objet Mme Eya cheikh

Cette méthode à l’inverse de la méthode getClass doit pratiquement être redéfinie. Elle
permet d’obtenir la représentation d’un objet sous forme d’une chaîne de caractères. Par
défaut l’implémentation de cette méthode dans la classe Object renvoie le nom de la classe
suivi du hashcode de l’instance.
Exemple
Client c1 = new Client("n1", "p1", "tunis", "Particulier");
System.out.println(c1.toString());

Le résultat obtenu est


 Ex2.Client@3a09a47d
Une redéfinition possible de la méthode toString pour la classe Personne est la suivante :
public String toString() {
String ch;
ch = "nom : " + this.getNom() + "\r\n";
ch = ch + "prenom :" + this.getPrenom();
return ch;
}

Remarque :
L’appel de la méthode toString est parfois implicite lorsque l’on passe un objet comme
paramètre à une méthode. Les deux syntaxes suivantes sont donc équivalentes :
Client c1 ;
c1 = new Client("n1", "p1", "tunis", "Particulier");
System.out.println(c1.toString());
// ou bien
System.out.println(c1);

Le résultat obtenu est :


nom : n1
prenom :p1

15
Programmation orientée objet Mme Eya cheikh

QCM
1. Le langage Java ne supporte pas :

o Le polymorphisme

o L'héritage multiple

o L'encapsulation

2. L'affirmation suivante est-elle vraie ?


Lors de la spécialisation d'une classe en une classe dérivée, la classe dérivée peut
posséder de nouveaux membres

o oui

o non

3. Une classe fille et sa classe mère ont une relation « est un »


o vrai
o faux

4. Avec quel mot clé peut-on accéder aux méthodes d'une classe mère lorsque nous créons
classe héritée ?

o this

o super

o hyper

5. Les méthodes et propriétés private d'une classe mère ne sont pas accessibles dans la
classe

fille.

o oui

o non

6. Quelle classe n’a pas de classe mère ?

16
Programmation orientée objet Mme Eya cheikh

o Orpheline

o String

o Object

o une classe abstraite

7. Qu'est-ce qui ne va pas dans ce code (cette classe est héritée d'une classe nommée A)
?

class B {

public B(){
super();
}}
o Mauvaise utilisation de super();

o il manque une accolade dans ce code.

o La classe B n'est pas héritée de la classe A.

8. Que va afficher ce code ?

public class A{
public A(){
System.out.println("1");
}
}
public class B extends A{ }

public class Test {


public static void main(String[] args)
{
B b = new B(); }

17
Programmation orientée objet Mme Eya cheikh

}
o Rien
o 1
o Erreur de compilation
9. Pour empêcher une classe d'être étendue, quel est le mot réservé que l'on utilise dans

la déclaration de classe ?

o transient

o final

o abstract

o native

10. Le code:
class A{int i=10; void f(){System.out.print(" i="+i);}}

class B extends A{ static int i=0; void f(){System.out.print("i="+i);super.f(); }}

avec le morceau de code: A a=new B();a.f();

o provoque une erreur à l’exécution


o provoque une erreur à la compilation
o affiche i=10 i=10
o affiche i=0 i=10
11. lesquelles parmi ces prépositions sont vraies ? (2 bonnes réponses)
class C

{ C(String s){}}

class D extends C{

D(){}}

o Compilation sans erreurs


o Pour que la compilation aboutit il faut ajouter le constructeur D(String s){}
à la classe D

18
Programmation orientée objet Mme Eya cheikh

o Pour que la compilation aboutit il faut ajouter le constructeur par défaut


C(){} à la classe C
o Pour que la compilation aboutit il faut remplacer D(){} par D(){super("") ;}
dans la classe D
o Pour que la compilation aboutit il faut remplacer C(String s){} par
C(){super("") ;} dans la classe C

19

Vous aimerez peut-être aussi