Vous êtes sur la page 1sur 44

Héritage en Java

Professeur: M. Joundi
L’héritage (3) : définition
• Héritage : mécanisme permettant 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.

• La classe parente est la superclasse.


• La classe qui hérite est la sous-classe.
L’héritage avec Java (1)
• Java implémente le mécanisme d'héritage simple qui
permet de "factoriser" de l'information grâce à une
relation de généralisation / spécialisation entre deux
classes.
• Pour le programmeur, il s'agit d'indiquer, dans la
sous-classe, le nom de la superclasse dont elle hérite.
• Par défaut toutes classes Java hérite de la classe
Object
• L'héritage multiple n'existe pas en Java.
• Mot réservé : extends
L’héritage avec Java (2)

Personne
class Personne
nom : String
{ date_naissance : Date
protected String nom;
protected Date date_naissance;
// ...
}

class Employe extends Personne Employe


{ salaire : Double

protected float salaire;


// ...
}

class Etudiant extends Personne


{ Etudiant
protected int numero_carte_etudiant; numero_carte_etudiant : Integer
// ...
}
L’héritage avec Java (3)
Constructeurs et héritage:
– par défaut le constructeur d’une sous-classe
appelle le constructeur "par défaut" (celui qui ne
reçoit pas de paramètres) de la superclasse.
Attention donc dans ce cas que le constructeur
sans paramètre existe toujours dans la
superclasse...
– Pour forcer l'appel d'un constructeur précis, on
utilisera le mot réservé super. Cet appel devra être
la première instruction du constructeur.
L’héritage avec Java (4)

public class Employe extends Personne public class Personne


{ {
public Employe () {} public String nom, prenom;
public Employe (String nom, public int anNaissance;
String prenom, public Personne()
int anNaissance) {
{ nom=""; prenom="";
super(nom, prenom, anNaissance); }
} public Personne(String nom,
} String prenom,
int anNaissance)
{
Appel explicite à ce constructeur this.nom=nom;
avec le mot clé super this.prenom=prenom;
this.anNaissance=anNaissance;
}
}
L’héritage avec Java (5)

public class Personne


{ public class Object
public String nom, prenom; {
public int anNaissance; public Object()
public Personne() {
{ … / ...
nom=""; prenom=""; }
} }
public Personne(String nom,
String prenom,
int anNaissance) Appel par défaut dans le constructeur
{ de Personne au constructeur
this.nom=nom; par défaut de la superclasse de
this.prenom=prenom; Personne, qui est Object
this.anNaissance=anNaissance;
}
}
Exercice
• Ecrire une classe Animal qui dispose d’un attribut
entiernbPattes . Cette classe dispose des méthodes
suivantes :
– le constructeur, qui prend en argument un entier (le
nombre de pattes).
– String toString (), qui renvoie une chaîne de caractères
contenant le nombre de pattes de l’animal.
– affiche() qui affiche le nombre de pattes de l’animal.
• Ecrire une classe Autruche qui hérite de Animal
• Ecrire une classe Lapin qui hérite de Animal
• Ecrire une classe Main dans laquelle la méthode
main() crée un lapin et une autruche
Dans la classe Animal la méthode toString () renvoi le message :
Ceci et un animal de … pattes .
Dans la classe Autruche la méthode toString () renvoi le message :
Ceci et une autruche de … pattes .
Dans la classe Lapin la méthode toString () renvoi le message :
Ceci et un lapin de … pattes .
Remarque : les pointillées seront remplies par le nombre de pattes adéquate
Corrigé
• La classe Animal :
class Animal
{
protected int nbPattes;
Animal(int nb ){//constructeur
setNbPattes (nb );
}
//accesseur
publicint getNbPattes (){returnnbPattes ;}
//modifieur
publicvoid setNbPattes (int nb ){nbPattes =nb ;}
public StringtoString () {
return "Ceci est un animal doté de " +getNbPattes () + " pattes";
}
publicvoid affiche(){
System.out.println (toString ());
}
}
Corrigé (2)
• Les classes Autruche et Lapin :
class Autruche extends Animal
{
Autruche(int nb ){//constructeur
super(nb );
}
public String toString () {
return "Ceci est une autruche dotée de " +getNbPattes () + "
pattes";
}
}
class Lapin extends Animal
{
Lapin(int nb ){//constructeur
super(nb );
}
public String toString () {
return "Ceci est un lapin doté de " + getNbPattes () + " pattes";
}
}
Corrigé (3)
• La classe Main :
class Main
{
publicstatic void main(Stringargs[])
{
Autruche kiki = new Autruche(2);
Lapinbunny = new Lapin(4);
kiki.affiche();
bunny.affiche();
}
}
finale
• Classe finale : classe qui ne peut pas être
super-classe d'une autre classe
¨Syntaxe final class Z{
}
Exemple:
final class A { }
class B extends A{ }
génère l’erreur suivante à la compilation
Cannot inherit from final A
finale
• Méthode finale : Une sous classe ne pourra pas
redéfinir la méthode
• ¨Syntaxe dans le corps d'une classe (disons A)
final … méthode(…) { }
Example:
class A {
final void m(){ System.out.println("final method"); }
}
class B extends A{
void m(){ // génère une erreur à la compilation
System.out.println("never override a final method");
}
finale
• Champ final : ni la classe, ni aucune sous
classe ne peuvent changer la valeur initiale
du champ
• ¨Joue le rôle d'une constante d'objet ou de
classe
¨Syntaxe
final typeChamp nomChamp = valInitiale;
Redéfinir une méthode (overriding)
 une classe fille peut redéfinir une méthode
 ce qui signifie qu’elle peut réécrire une méthode
en gardant exactement :
 La même signature
 Le type de retour : peut être le même type ou du
type d’une classe fille
 lorsque l’on redéfinit une méthode
 cela signifie que l’on modifie son

implémentation
Redéfinir une méthode (overriding)

• Une méthode redéfinit ne peut pas avoir un


accès plus restrictif .
• Pour appeler une méthode de la super-classe, on
doit précéder le nom de la méthode par le mot clé
super
super.getNom()
Surcharger une méthode(overloading)

 une classe fille peut surcharger une méthode


 ce qui signifie qu’elle peut réécrire une méthode
en gardant le même nom mais pas la même
signature, c’est-à dire avec des paramètres
d’entrée différents mais le paramètre de retour
peut être différent .
 lorsque l’on surcharge une méthode,
 cela signifie que l’on ajoute un comportement

 et que l’on modifie son interface


OverLoad #Override
//NOT LEGAL
//Legal public class Foo{
public class Foo{ void go() { } }
void go() { } } public class Bar extends
public class Bar extends Foo {
Foo { String go() {
String go(int x) // Not legal! Can't change
{ return null; } } //only the return type
return null; } }
• Etant donné:
class Clidders {
public final void flipper() { System.out.println("Clidder"); }
}
public class Clidlets extends Clidders {
public void flipper() {
System.out.println("Flip a Clidlet");
super.flipper();
}
public static void main(String [] args) {
new Clidlets().flipper();
}
}
• Quel est le résultat :
A Flip a Clidlet
B Flip a Clidder
C Flip a Clidder
Flip a Clidlet
D Flip a Clidlet
Flip a Clidder
E Compilation fails.
 
• Etant donné:
class Clidders {
public final void flipper() { System.out.println("Clidder"); }
}
public class Clidlets extends Clidders {
public void flipper() {
System.out.println("Flip a Clidlet");
super.flipper();
}
public static void main(String [] args) {
new Clidlets().flipper();
}
}
• Quel est le résultat :
A Flip a Clidlet
B Flip a Clidder
C Flip a Clidder
Flip a Clidlet
D Flip a Clidlet
Flip a Clidder
E Compilation fails.
 
• E is correct. final methods cannot be overridden.
class Top {
public Top(String s) { System.out.print("B"); }
}
public class Bottom2 extends Top {
public Bottom2(String s) { System.out.print("D"); }
public static void main(String [] args) {
new Bottom2("C");
System.out.println(" ");
}}
• Quel est le résultat?
A BD
B DB
C BDC
D DBC
E Compilation fails. 
class Top {
public Top(String s) { System.out.print("B"); }
}
public class Bottom2 extends Top {
public Bottom2(String s) { System.out.print("D"); }
public static void main(String [] args) {
new Bottom2("C");
System.out.println(" ");
}}
• Quel est le résultat?
A BD
B DB
C BDC
D DBC
E Compilation fails. 
• E is correct
class Clidder {
private final void flipper() { System.out.println ("Clidder"); }
}
 
public class Clidlet extends Clidder {
public final void flipper() { System.out.println("Clidlet"); }
public static void main(String [] args) {
new Clidlet().flipper();
}
}
• Quel est le résultat?
A Clidlet
B Clidder
C Clidder
Clidlet
D Clidlet
Clidder
E Compilation fails.
class Clidder {
private final void flipper() { System.out.println ("Clidder"); }
}
 
public class Clidlet extends Clidder {
public final void flipper() { System.out.println("Clidlet"); }
public static void main(String [] args) {
new Clidlet().flipper();
}
}
• Quel est le résultat?
A Clidlet
B Clidder
C Clidder
Clidlet
D Clidlet
Clidder
E Compilation fails.

A is correct
Polymorphisme
Question

Soit l’exemple d’une classe Etudiant qui hérite de la classe
Personne.
Soit une méthode getNom() de Personne
qui est redéfinie dans Etudiant

quelle méthode getNom() sera exécutée dans le code
suivant, celle de Personne ou celle de Etudiant?
Personne a =new Etudiant(5);
a.getNom();


la méthode appelée ne dépend que du type réel
(Etudiant) de l’objet a et pas du type déclaré (ici
Personne )
 c’est la méthode de la classe Etudiant qui sera exécutée
Polymorphisme

 NomComplet peut être utilisé à la place de Nom


Polymorphisme

Nom[] noms = new Nom[4];


noms[0] = new NomComplet("Cantonna",
"Eric");
noms[1] = new Nom("Ronaldo");
noms[2] = new NomComplet("Overmars",
"Marc");
...
for (int i = 0; i < 4; i++) {

System.out.println(noms[i].getNom())
;
}
Polymorphisme

même code d’invocation de getNom()


toujours sur un objet déclaré de type Nom


System.out.println(noms[i].getNom());

appliqué aux objets de types différents…


on a un effet différent selon l’objet qui reçoit le message, et plus


précisément selon sa classe.
Polymorphisme
(autre exemple)
Polymorphisme
(autre exemple)
public class Polymorph {
void prnt() {
System.out.println("poly");
}
}
public class MonomorphA extends Polymorph {
void prnt() {
System.out.println("type A");
}
}
public class MonomorphB extends Polymorph {
void prnt() {
System.out.println("type B");
}
Polymorphisme
(autre exemple)

...
Polymorph pm = new Polymorph();
pm.prnt();
pm = new MonomorphA();
pm.prnt();
pm = new MonomorphB();
pm.prnt();
héritage & ( Upcasting /Downcasting)
/

Upcasting
faire passer une classe dérivée pour sa super-classe

sans risque

toute méthode de la super-classe est aussi une méthode de la classe


dérivée (par définition)
Downcasting
faire passer une super-classe pour une classe dérivée

pas sans risque

la classe dérivée étend la super-classe


peut avoir des méthodes que la super-classe n’a pas
1. class Plant {
2. String getName() { return "plant"; }
3. Plant getType() { return this; }
4. }
5. class Flower extends Plant {
6. // insert code here
7. }
8. class Tulip extends Flower {}
• Quelle est la(les)ligne(s) de code à insérer à la ligne 6
est qui réussira à la compilation.
A Flower getType() { return this; }
B String getType() { return "this"; }
C Plant getType() { return this; }
D Tulip getType() { return new Tulip() ;}
1. class Plant {
2. String getName() { return "plant"; }
3. Plant getType() { return this; }
4. }
5. class Flower extends Plant {
6. // insert code here
7. }
8. class Tulip extends Flower {}
• Quelle est la(les)ligne(s) de code à insérer à la ligne 6
est qui réussira à la compilation.
A Flower getType() { return this; }
B String getType() { return "this"; }
C Plant getType() { return this; }
D Tulip getType() { return new Tulip() ;}
A, C, and D
9 Given:
1. class Programmer {
2. Programmer debug() { return this; }
3. }
4. class SCJP extends Programmer {
5. // insert code here
6. }
• Quelle est la(les)ligne(s) de code à insérer à la ligne 5 est qui
réussira à la compilation.
A Programmer debug() { return this; }
B SCJP debug() { return this; }
C Object debug() { return this; }
D int debug() { return 1; }
E int debug(int x) { return 1; }
F Object debug (int x) { return this; }
9 Given:
1. class Programmer {
2. Programmer debug() { return this; }
3. }
4. class SCJP extends Programmer {
5. // insert code here
6. }
• Quelle est la(les)ligne(s) de code à insérer à la ligne 5 est qui réussira
à la compilation.
A Programmer debug() { return this; }
B SCJP debug() { return this; }
C Object debug() { return this; }
D int debug() { return 1; }
E int debug(int x) { return 1; }
F Object debug (int x) { return this; }

A, B, E, and F
10 Given:
class Uber {
static int y = 2;
Uber(int x) { this(); y = y * 2; }
Uber() { y++; }
}
class Minor extends Uber {
Minor() { super(y); y = y + 3; }
public static void main(String [] args) {
new Minor();
System.out.println(y);
}}
Quel est le résultat?
A 6
B 7
C 8
D 9
E Compilation fails.
F An exception is thrown.
10 Given:
class Uber {
static int y = 2;
Uber(int x) { this(); y = y * 2; }
Uber() { y++; }
}
class Minor extends Uber {
Minor() { super(y); y = y + 3; }
public static void main(String [] args) {
new Minor();
System.out.println(y);
}}
Quel est le résultat?
A 6
B 7
C 8
D 9
E Compilation fails.
F An exception is thrown.
D is correct
1. class Dog { }
2. class Beagle extends Dog { }
3.
4. class Kennel {
5. public static void main(String [] arfs) {
6. Beagle bl = new Beagle();
7. Dog dogl = new Dog();
8. Dog dog2 = bl;
9. // insert code here
10. } }
• Quelle est la(les)ligne(s) de code à insérer à la ligne 9 est qui
réussira à la compilation.
A Beagle b2 = (Beagle) dog1;
B Beagle b3 = (Beagle) dog2;
D Beagle b4 = dog2;
E None of the above statements will compile.
1. class Dog { }
2. class Beagle extends Dog { }
3.
4. class Kennel {
5. public static void main(String [] arfs) {
6. Beagle bl = new Beagle();
7. Dog dogl = new Dog();
8. Dog dog2 = bl;
9. // insert code here
10. } }
• Quelle est la(les)ligne(s) de code à insérer à la ligne 9 est qui réussira à
la compilation.
A Beagle b2 = (Beagle) dog1;
B Beagle b3 = (Beagle) dog2;
D Beagle b4 = dog2;
E None of the above statements will compile.

A and B are,correct
13 Given the following,
1. class X { void dol() { } }
2. class Y extends X { void do2() { } }
3.
4. class Chrome {
5. public static void main(String [] args) {
6. X x1 = new X();
7. X x2 = new Y();
8. Y y1 = new Y();
9. // insert code here
10. } }
• Quelle est la(les)ligne(s) de code à insérer à la ligne 9 est qui réussira
à la compilation.
A x2.do2( );
B (Y) x2. do2( );
C ((Y)x2).do2();
D None of the above statements will compile.
13 Given the following,
1. class X { void dol() { } }
2. class Y extends X { void do2() { } }
3.
4. class Chrome {
5. public static void main(String [] args) {
6. X x1 = new X();
7. X x2 = new Y();
8. Y y1 = new Y();
9. // insert code here
10. } }
• Quelle est la(les)ligne(s) de code à insérer à la ligne 9 est qui réussira
à la compilation.
A x2.do2( );
B (Y) x2. do2( );
C ((Y)x2).do2();
D None of the above statements will compile.

C is correct
Le contrôle d'accès

Modificateur même class même Package Sous class Univers

private oui

default oui oui

protected oui oui oui

public oui oui oui oui


Gestion d’heures complémentaires
• Chaque enseignant de l’université effectue un certain nombre d’heures
d’enseignement dans une année. Suivant le statut de l’enseignant, un certain
nombre de ces heures peut-être considéré comme complémentaire. Les heures
complémentaires sont payées séparément à l’enseignant. Les volumes horaires
sont exprimés en heures entières et le prix d’une heure complémentaire est de 35
Euros.
• Le nom et le nombre d’heures total d’un enseignant sont fixés à sa création, puis
seul le nom peut être librement consulté (méthode nom()).
• D’autre part on veut pouvoir librement consulter un enseignant sur son volume
d’heures complémentaires (méthode hc()) et sur la rétribution correspondante
(méthode retribution()).
• Il y a deux types d’enseignants :
• les intervenants extérieurs : toutes les heures effectuées sont complémentaires,
• les enseignants de la fac : seules les heures assurées au delà d’une charge
statutaire de 192h sont complémentaires.
A Modéliser les enseignants .
B Comment modifier le modèle pour y introduire les étudiants de troisième cycle
qui assurent des enseignements: toutes les heures effectuées sont
complémentaires mais dans la limite de 96 heures.

Vous aimerez peut-être aussi