HÉRITAGE ET POLYMORPHISME
En Java, l’héritage est une sorte d’extension des classes : on utilise « extends »
Une référence d’objet de type B peut référencer un objet de type A, mais l’inverse est
faux.
Exemple :
class B { …………… }
class A extends B {………………}
B b = new B() ;
A a = new A() ;
b=a; //correct
a=b; //incorrect
//Erreur, car abs et ord sont privés à la classe mère, donc invisible pour la classe fille.
}
}
Exemple:
class Point {
protected int abs, ord; //deux attributs protégés
public Point(int a, int b){
abs = a;
ord = b;
}
}
class PointColore extends Point {
private String couleur;
public PointColore (int a, int b, String c) {
super (a, b); //appel au constructeur de la classe mère
couleur = c;
System.out.println("abs et ord sont :" + super.abs + "et" + super.ord) ;
//accès autorisé à abs et ord, ils sont accessibles par les méthodes des classes filles
}
}
Remarques :
Lorsque les attributs abs et ord de la classe Point sont déclarés protégés, alors ils sont
considérés aussi des attributs de la classe PointColore. On peut alors les accéder aussi bien
par super que par this. ( super.abs ou this.abs donnent le même résultat)
Si on déclare un attribut abs dans PointColore alors dans ce cas, this.abs fait référence à
l’attribut de PointColore et super.abs fait référence à l’attribut de Point.
Exemple:
class Point {
...
protected void afficher(){
System.out.println(“abs = ” + abs + “ord = ” + ord);
}
}
class PointColore extends Point {
...
public void afficherCouleur(){
System.out.println(“couleur = ” + couleur);
}
}
...
public static void main(String args[]) {
PointColore pc = new PointColore (1, 2, “noir”);
pc.afficher() ; //objet pc utilise afficher() de Point comme si c’était sa méthode
pc.afficherCouleur() ;
}
Dans cet exemple, l’affichage de tous les attributs d’un PointColore doit passer par l’appel de
la méthode afficher() de Point et afficherCouleur() de PointColore.
La méthode afficher() de Point est partiellement utile à PointColore. On pourra ajouter une
méthode void afficher() à la classe PointColore et ainsi ne plus utiliser celle de Point : on
appelle ça la redéfinition de méthode.
2. Redéfinition des méthodes héritées
Une méthode héritée peut être redéfinie si sa version initiale n’est pas satisfaisante pour la
classe dérivée.
La redéfinition consiste à conserver la signature de la méthode (même nom, même
nombre, type et position des paramètres, même type de retour) et à proposer un code
différent.
En java, une classe dérivée peut surcharger une méthode d’une classe ascendante.
La recherche d’une méthode acceptable ne se fait qu’en remontant la hiérarchie
d’héritage, jamais en la descendant.
Exemple:
class A {
...
public void f (int n){ ...}
}
}
class B extends A {
...
public void f (float x){ ...}
}
}
A a ; B b ;
int n; float x ;
...
a.f(n) ; //appelle f(int) de A
a.f(x) ; //erreur de compilation
b.f(n) ; //appelle f(int) de A
b.f(x) ; //appelle f(float) de B
Un objet de type classe de base peut stocker la référence d’un objet de type classe dérivée.
Mais l’inverse n’est pas autorisé. Pour le faire il faut passer par le casting.
6. Le polymorphisme
6.1. Les méthodes polymorphes
Une méthode polymorphe est une méthode déclarée dans une super-classe et redéfinie par
une sous-classe.
Les méthodes polymorphes permettent de prévoir des opérations similaires sur des objets
de natures différentes
Les méthodes « final » ne peuvent être redéfinies et ne sont donc pas polymorphes.
6.2. Définition du polymorphisme
Il s’agit d’invoquer (appeler) des méthodes sans connaitre la nature de l’objet
correspondant
L’appel se fait à partir d’une référence du même type que l’objet correspondant ou de type
sa classe de base. (on peut remonter à tous les niveaux de sa classe de base)
8. Exercices
Exercice 1 :
Une entreprise engage trois types d’employés à savoir : Des contractuels (travaillants pour un
contrat à durée déterminée), des permanents et des vacataires (travaillants par heure). Pour
chacun de ces employés, l’entreprise retient les informations suivantes : nom, num CIN,
adresse et salaire.
Les vacataires sont payés mensuellement en fonction du nombre d’heure effectué pendant le
moi et du prix de l’heure. Les contractuels sont payés par mois, ils reçoivent un salaire de
base. Les permanents sont payés mensuellement un salaire de base en plus d’une prime de
rendement. Un service de calcul de salaire est prévu pour chaque type d’employé.
1. Schématiser la relation d’héritage entre les classes : Employe, Vacataire, Contractuel et
Permanent. (indiquer les attributs et les méthodes)
2. Définir la classe mère Employe :
- Les champs sont : nom, CIN, adresse et salaire
- Une méthode afficher()
3. Définir les autres classes filles sachant que chacune contient :
- Les attributs nécessaires pour calculer le salaire
- Une méthode calculSalaire()
- Une méthode afficher()
4. dans le programme principal, créer un vecteur qui contient trois employés de types
différents et les afficher.
Exercice 2 :
Soit la classe Test suivante. Dites si les instructions 1 à 8 sont valides ou non. En cas d’une
instruction non valide, préciser s’il s’agit d’une erreur de compilation ou d’exécution.
class Test {
public static void main (String args[]){
C1 o1 = new C1();
C1 o2 = new C11();
C111 o3 = new C111();
C11 o4 = new C111();
C1 o5 = new C111();
o1 = o2; //instruction 1
o1 = o3; //instruction 2
o3 = o1; //instruction 3
o4 = o5; //instruction 4
o3 = (C111) o1; //instruction 5
o4 = (C11) o5; //instruction 6
o4 = (C111) o2; //instruction 7
o3 = (C11) o5; //instruction 8
}
}
class C1 {}
class C11 extends C1 {}
class C111 extends C11 {}
Cours POO (Java) - 40 - Amir Souissi © 2018
Chapitre 4 Héritage et Polymorphisme
Exercice 3 :
1. Ecrire une Classe Point avec les attributs suivants : x : l’abscisse, y : l’ordonnée. La classe
Point doit disposer des constructions suivantes : Point(), Point(x,y)
La classe Point doit contenir les accesseurs et mutateurs et aussi une méthode toString()
donnant une représentation du point.
2. Ecrire une classe Rectangle héritant de Point avec les attributs suivants : longueur,
largeur. La classe rectangle doit disposer des constructeurs suivants : Rectangle(),
Rectangle (x,y, longueur, largeur)
La classe Rectangle doit contenir des accesseurs et mutateurs et aussi les méthodes
suivantes : aire() ; donne l’aire du rectangle, toString() : donne une représentation du
rectangle (redéfinition)
3. Ecrire une classe Parallélogramme héritant de Rectangle avec l’attribut hauteur. La classe
Parallélogramme doit disposer des constructeurs suivants : Parallélogramme(),
Parallélogramme (x, y, longueur, largeur, hauteur)
La classe Parallélogramme doit contenir des accesseurs et des mutateurs et aussi les
méthodes suivantes : aire() : donne l’aire du parallélogramme (redéfinition), volume() :
donne le volume du parallélogramme, toString() : donne une représentation du
parallélogramme (redéfinition).
4. Ecrire une classe de test afin de tester les classes.