[Go to site: main page, start]

0% ont trouvé ce document utile (0 vote)
4 vues56 pages

Cours Java1

Transféré par

abdoulsany
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
4 vues56 pages

Cours Java1

Transféré par

abdoulsany
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Heritage

et Polymorphisme
Philippe Genoud
dernière mise à jour : 19/12/2017

©
© Philippe
Philippe GENOUD
GENOUD UGA
UJF Décembre 2017
2009 1
Surclassement
 La réutilisation du code est un aspect important de l'héritage, mais ce n'est
peut être pas le plus important
 Le deuxième point fondamental est la relation qui relie une classe à sa super-
classe :

Une classe B qui hérite de la classe A peut être vue comme un


sous-type (sous ensemble) du type défini par la classe A.

Etudiant
Un EtudiantSportif est un Etudiant

L’ensemble des étudiants sportifs est


EtudiantSportif inclus dans l’ensemble des étudiants

© Philippe GENOUD UGA Décembre 2017 2


Surclassement
 tout objet instance de la classe B peut être aussi vu comme une instance de
la classe A.
 Cette relation est directement supportée par le langage JAVA :

 à une référence déclarée de type A il est possible d'affecter une valeur qui
est une référence vers un objet de type B (surclassement ou upcasting)

Etudiant Etudiant e; A
e = new EtudiantSportif(...);
B C

EtudiantSportif D E
F
C c;
c = new D();
 plus généralement à une référence d'un type donné, il est possible c = new E();
d'affecter une valeur qui correspond à une référence vers un objet c = new F();
dont le type effectif est n'importe quelle sous-classe directe ou c = new A();
indirecte du type de la référence c = new B();
© Philippe GENOUD UGA Décembre 2017 3
Surclassement
 Lorsqu'un objet est "sur-classé" il est vu par le compilateur comme un objet du type
de la référence utilisée pour le désigner
 Ses fonctionnalités sont alors restreintes à celles proposées par la classe du type
de la référence
Etudiant
EtudiantSportif es; String nom;
String prénom;
es = new EtudiantSportif("DUPONT","Jean", int age;
25,..,"Badminton",..); …
public Etudiant(String n, String p, int a ...)
es public void affiche()
Etudiant e;
e = es; // upcasting public int nbInscriptions()
...
e
[Link]();
[Link](); isa
DUPONT EtudiantSportif
[Link]();
[Link](); Jean
String sportPratiqué;
25 …
[Link](); ...
public EtudiantSportif (String n, String p,
[Link](); Badminton int a, …, String s, ...)
... public void affiche()
Le compilateur refuse ce message: public double bonusSportif()
pas de méthode bonusSportif ...
définie dans la classe Etudiant
© Philippe GENOUD UGA Décembre 2017 4
Lien dynamique
Résolution des messages

Etudiant
 Que va donner [Link]() ? public void affiche() {
[Link](
"Nom : "+nom+"\n"
"Prénom : "+prénom+"\n"
Etudiant e = new EtudiantSportif( "Age : "+age+ ...);
"DUPONT","Jean",25,.., }
"Badminton",..); ?
[Link]();
e

isa ? EtudiantSportif
DUPONT
Jean public void affiche() {
[Link]();
25 [Link](
... "Sport" : "+sport+"\n"
+ ...);
Badminton }
...

© Philippe GENOUD UGA Décembre 2017 5


Lien dynamique
Résolution des messages

Lorsqu'une méthode d'un objet est accédée


au travers d'une référence "surclassée", Etudiant
c'est la méthode telle qu'elle est définie
public void affiche() {
au niveau de la classe effective de [Link](
l'objet qui est en fait invoquée et exécutée "Nom : "+nom+"\n"
"Prénom : "+prénom+"\n"
Etudiant e = new EtudiantSportif( "Age : "+age+ ...);
"DUPONT","Jean",25,.., }
"Badminton",..); ?
[Link]();
e

isa ? EtudiantSportif
DUPONT
Nom : DUPONT public void affiche() {
Jean
Prénom : Jean [Link]();
25 Age : 25 [Link](
... … "Sport" : "+sport+"\n"
+ ...);
Badminton Sport : Badminton
}
...

© Philippe GENOUD UGA Décembre 2017 6


Lien dynamique
Mécanisme de résolution des messages

 Les messages sont résolus à l’exécution


 la méthode exécutée est déterminée à l'exécution (run-time) et non pas à la
compilation
 à cet instant le type exact de l'objet qui reçoit le message est connu

 la méthode définie pour le type réel de l’objet recevant le message est appelée
(et non pas celle définie pour son type déclaré).

public class A { Type


public void m() { déclaré obj A obj = new C();
[Link]("m de A");
} obj.m();
}
isa
m ? public class B extends A {
public void m() { m de B
Type
[Link]("m
[Link]("mde
deB");
B"); effectif
}
}

 ce mécanisme est désigné sous le terme de lien-


public class C extends B {
m ? }
dynamique (dynamic binding, late-binding ou
run-time binding)

© Philippe GENOUD UGA Décembre 2017 7


Lien dynamique
Vérifications statiques
 A la compilation: seules des vérifications statiques qui se basent sur le type déclaré
de l’objet (de la référence) sont effectuées
 la classe déclarée de l’objet recevant un message doit posséder une méthode
dont la signature correspond à la méthode appelée.
A obj = new B();
public class A {
public void m1() {
Type obj.m1();
[Link]("m1 de A");
déclaré obj
} obj.m2();
}
[Link]: cannot resolve symbol
public class B extends A { symbol : method m2 ()
public void m1() {
[Link]("m1 de B");
location: class A
} obj.m2();
public void m2() { ^
[Link]("m2 de B"); 1 error
}
}

 garantir dès la compilation que les messages pourront être résolus au moment de
l’exécution  robustesse du code

© Philippe GENOUD UGA Décembre 2017 8


Lien dynamique
Vérifications statiques

 à la compilation il n’est pas possible de déterminer le type exact de l'objet


récepteur d'un message

public class A {
A obj = new B();
A obj;
public void m1() { Type obj.m1();
for (int i = 0; i < 10; i++) {
[Link]("m1 de A"); déclaré obj hasard = [Link]()
} obj.m2();
} if ( hasard < 0.5)
obj = newcannot
[Link]: A(); resolve symbol
public class B extends A { else : method m2 ()
symbol
public void m1() {
[Link]("m1 de B"); location:
obj = class A
new B();
} obj.m2();
public void m2() { ^
[Link]("m2 de B"); obj.m1();
1 error
} }
}

 vérification statique: garantit dès la compilation que les messages pourront être résolus
au moment de l’exécution

© Philippe GENOUD UGA Décembre 2017 9


Lien dynamique
Choix des methodes, sélection du code

Le choix de la méthode à exécuter est


effectué statiquement à la compilation
public class A {
public void m1() { en fonction du type des paramètres
[Link]("m1 de A"); A refA = new A();
}

public void m1(int x) { refaA.m1();


[Link]("m1(x) de A"); invokevirtual … <Method m1()>
} refA.m1(10);
}
invokevirtual … <Method m1(int)>
refA = new B();
public class B extends A { invokevirtual … <Method m1()>
public void m1() {
refA.m1();
[Link]("m1 de B");
} Byte-code
public void m2() { Compilation
[Link]("m2 de B");
}
} La sélection du code à exécuter est effectuée
dynamiquement à l’exécution en fonction du
type effectif du récepteur du message

© Philippe GENOUD UGA Décembre 2017 10


Polymorphisme
A quoi servent l’upcasting et le lien dynamique ?
A la mise en œuvre du polymorphisme
 Leterme polymorphisme (du grec πολύμορφος , « multiforme »), ) décrit la
caractéristique d'un élément qui peut se présenter sous différentes formes.

 Enprogrammation par objets, on appelle polymorphisme


 le fait qu’un objet d’une classe puisse être manipulé comme s’il
appartenait à une autre classe.
 le fait que la même opération puisse se comporter différemment sur
différentes classes de la hiérarchie.

 "Lepolymorphisme constitue la troisième caractéristique essentielle d'un


langage orienté objet après l'abstraction des données (encapsulation) et
l'héritage" Bruce Eckel "Thinking in JAVA"

© Philippe GENOUD UGA Décembre 2017 11


Polymorphisme
ClasseA

méthodeX()

ClasseB ClasseC

méthodeX()

ClasseD ClasseE ClasseF


méthodeX()

Surclassement un cas particulier de


ClasseA objA; la référence peut
désigner des objets de polymorphisme
classe différente
objA = ... (n’importe quelle sous
(polymorphisme par sous-typage)
classe de ClasseA)
[Link]();
+ manipulation uniforme des objets
de plusieurs classes par
Lien dynamique l'intermédiaire d'une classe de
Le comportement est
différent selon la classe base commune
effective de l’objet

© Philippe GENOUD UGA Décembre 2017 12


Polymorphisme
liste peut contenir des étudiants de n’importe quel type
GroupeTD td1 = new GroupeTD(); public class GroupeTD{
[Link](new Etudiant("DUPONT", …));
[Link](new EtudiantSportif("BIDULE", Etudiant[] liste = new Etudiant[30];
"Louis", … , "ski alpin"); int nbEtudiants = 0;
...
public void ajouter(Etudiant e) {
Etudiant if (nbEtudiants < [Link])
liste[nbEtudiants++] = e;
public void affiche(){ }
[Link](
"Nom : "+nom+"\n" public void afficherListe(){
"Prénom : "+prénom+"\n"
"Age : "+age+ ...);
for (int i=0;i<nbEtudiants; i++)
} liste[i].affiche();
}
}

EtudiantSportif EtudiantEtranger Si un nouveau


type d’étudiant
public void affiche() { public void affiche(){ est défini,
[Link](); [Link]();
[Link]( [Link]( le code de
"Sport" : "+sport+"\n" "Nationalité" : "+pays+"\n" GroupeTD
+ ...); + ...); reste inchangé
} }

© Philippe GENOUD UGA Décembre 2017 13


Polymorphisme
 En utilisant le polymorphisme en association à la liaison
dynamique
 plus besoin de distinguer différents cas en fonction de la classe
des objets
 possible de définir de nouvelles fonctionnalités en héritant de
nouveaux types de données à partir d'une classe de base
commune sans avoir besoin de modifier le code qui manipule
l'interface de la classe de base

 Développement plus rapide


 Plus grande simplicité et meilleure organisation du code
 Programmes plus facilement extensibles
 Maintenance du code plus aisée
© Philippe GENOUD UGA Décembre 2017 14
Polymorphisme
Pour conclure

« Once you know that all method binding in Java


happens polymorphically via late binding,
you can always write your code to talk to the base class,
and know that all the derived-class cases will work
correctly using the same code.
Or put it another way, you send a message to an object
and let the object figure out the right thing to do »
Bruce Eckel, Thinking in Java

© Philippe GENOUD UGA Décembre 2017 15


Surcharge et polymorphisme
public class ClasseC {

public static void methodeX(ClasseA a){

surcharge
ClasseA [Link]("param typeA");
}

public static void methodeX(ClasseB b){


ClasseB [Link]("param typeB");
}

ClasseA refA = new ClasseA();


[Link](refA); param TypeA
ClasseB refB = new ClasseB();
[Link](refB); param TypeB
refA = refB; // upCasting
[Link](refA); param
?????TypeA

invokestatic … <Method void methodX( ClasseA )>


Le choix de la méthode à exécuter est Byte-code
effectué à la compilation en fonction des
types déclarés : Sélection statique
© Philippe GENOUD UGA Décembre 2017 16
Downcasting
ClasseX obj = …
ClasseA a = (ClasseA) obj;

 Le downcasting (ou transtypage) permet de « forcer un type » à la compilation


 C’est une « promesse » que l’on fait au moment de la compilation.

 Pour que le transtypage soit valide, il faut qu’à l’exécution le type effectif de
obj soit « compatible » avec le type ClasseA
 Compatible : la même classe ou n’importe quelle sous classe de ClasseA
(obj instanceof ClasseA)
 Si la promesse n’est pas tenue une erreur d’exécution se produit.

 ClassCastException est levée et arrêt de l’exécution

[Link]: ClasseX
at [Link]([Link])

© Philippe GENOUD UGA Décembre 2017 17


A propos de equals
 Tester l’égalité de deux objets de la même classe
public class Object { De manière générale, il vaut mieux
...
public boolean equals(Object o) éviter de surcharger des méthodes
return this == o; en spécialisant les arguments
}
...
}
public boolean equals(Point pt) {
return this.x == pt.x && this.y == pt.y;
public class Point { }
private double x;
surcharge (overloads) la méthode
private double y;
equals(Object o) héritée de Object
...
Point p1 = new Point(15,11);
} Point p2 = new Point(15,11);
[Link](p2); --> true
Object o = p2;
invokevirtual … <Method equals(Object)> [Link](o) --> false

Le choix de la méthode à exécuter est effectué [Link](p1) --> false


statiquement à la compilation
en fonction du type déclaré de l’objet récepteur du
message et du type déclaré du (des) paramètre(s)

© Philippe GENOUD UGA Décembre 2017 18


A propos de equals
 Tester l’égalité de deux objets de la même classe
public class Object {
@Override
...
public boolean equals(Object o) public boolean equals(Object o) {
return this == o if (this == o)
} return true;
...
} if (! (o instanceof Point))
public boolean equals(Point pt) {
return false;
return this.x == pt.x && this.y == pt.y;
public class Point { Point pt = (Point) o; // downcasting
}
return this.x == pt
o.x && this.y == pto.y;
private double x;
private double y; redéfinir (overrides) la méthode
} equals(Object o) héritée de Object
...
Point p1 = new Point(15,11);
} Point p2 = new Point(15,11);
[Link](p2) -->
--> true
true
Object o = p2;
[Link](o) -->
--> false
true

[Link](p1) -->
--> false
true

© Philippe GENOUD UGA Décembre 2017 19


Upcasting/Downcasting
A class A {
public void ma() {
ma() [Link]("methode ma définie dans A");
}
} class E extends C {
B C public void ma() {
[Link]("methode ma redéfinie dans E");
}
public void me() {
D E }
[Link]("methode me définie dans E");

ma() } class F extends E {


public void mf() {
me() [Link]("methode mf définie dans f");
}

C c = new F(); F public void me() {


[Link]("methode me redéfinie dans F");
mf() }
me() }

compilation exécution
[Link](); La classe C hérite d'une méthode ma  méthode ma définie dans E

Cannot find symbol : metod mf()


[Link]();
Pas de méthode mf() définie au niveau de la classe C

Incompatible types
B b = c; Un C n'est pas un B
Incompatible types
E e = c; Un C n'est pas forcément un E

E e = (E)c; Transtypage (Dowcasting), le compilateur ne fait pas de vérification


 méthode me définie dans F
[Link](); La classe E définit bien une méthode me

D d = (D) c; Transtypage (Dowcasting), le compilateur ne fait pas de vérification ClassCastException Un F n'est pas un D
© Philippe GENOUD UGA Décembre 2017 20
Héritage et abstraction
classes abstraites
Philippe Genoud

©
© Philippe
Philippe GENOUD
GENOUD UGA
UJF Décembre 2017
2009 21
Classes Abstraites
Exemple introductif
 un grand classique les formes géométriques
 on veut définir une application permettant de manipuler des formes géométriques
(triangles, rectangles, cercles…).
 chaque forme est définie par sa position dans le plan

 chaque forme peut être déplacée (modification de sa position), peut calculer son
périmètre, sa surface
largeur
v2
r
hauteur
x,y
x,y v1
x,y

Attributs : Attributs : Attributs :


double x,y; //centre du cercle double x,y; //coin inférieur gauche double x,y; //1 des sommets
double r; // rayon double largeur, hauteur; double x1,y1; // v1
Méthodes : Méthodes : double x2,y2; // v2
deplacer(double dx, double dy) deplacer(double dx, double dy) Méthodes :
double surface() double surface() deplacer(double dx, double dy)
double périmètre() double périmètre(); double surface()
double périmètre();

Factoriser le code ?

© Philippe GENOUD UGA Décembre 2017 22


Classes abstraites
public class Forme {
protected double x,y; Exemple introductif
largeur
public Forme(double x, double y) { v2
this.x = x; r
hauteur
this.y = y;
x,y
}
x,y x,y v1
public void deplacer(double dx,
double dy) {
x += dx; y += dy; Forme
} double x,y; //point de référence
}
Forme (double x, y)
deplacer(double dx,dy)
public class Cercle extends Forme {
protected double r;

public Cercle(double x, double y,


double r) {
super(x,y);
this.r = r; Cercle Rectangle Triangle
}
double r; // rayon double largeur, hauteur; double x1,y1; // v1
public double surface(){ Cercle(double x,y,r) Rectangle(double x,y,l,h) double x2,y2; // v2
return [Link] * r * r; double surface() double surface() Triangle(double x,y,x1,y1,x2,y2)
}
double périmètre() double périmètre(); double surface()
protected double périmetre(){ double périmètre();
return 2 * [Link] * r;
}
}
© Philippe GENOUD UGA Décembre 2017 23
Classes abstraites
Exemple introductif
public class ListeDeFormes {
On veut pouvoir
public static final int NB_MAX = 30; gérer des listes
private Forme[] tabFormes = new Forme[NB_MAX];
private int nbFormes = 0; de formes
public void ajouter(Forme f) { On exploite le polymorphisme
if (nbFormes < NB_MAX)
tabFormes[nbFormes++] =f
la prise en compte de nouveaux
} types de forme ne modifie pas
le code
public void toutDeplacer(double dx,double dy) {
for (int i=0; i < NbFormes; i++)
tabFormes[i].deplacer(dx,dy);
Appel non valide car la méthode
} périmètre n’est pas implémentée
au niveau de la classe Forme
public double périmètreTotal() {
double perimTotal = 0.0; Définir une méthode
for (int i=0; i < nbFormes++; i++) périmètre dans Forme ?
perimTotal += tabFormes[i].périmètre();
return perimTotal; public double périmètre() {
erreur de
} return 0.0; // ou -1. ??
compilation
BOF

}
}

Une solution propre et élégante : les classes abstraites


© Philippe GENOUD UGA Décembre 2017 24
Classes abstraites
public abstract class Forme { la classe doit être
Classe abstraite protected double x,y; déclarée comme étant
explicitement abstraite
public Forme(double x, double y) {
this.x = x;
this.y = y;
}

public void deplacer(double dx,


on spécifie qu'un objet
double dy) {
de type Forme aura une
x += dx; y += dy;
méthode périmètre et
}
une méthode surface
Méthodes abstraites public abstract double périmètre() ;
par contre on ne sait pas
public abstract double surface() ; comment cela sera
implémenté 
}
méthodes sans corps :
 Utilité : ; au lieu de { … }

 définir des concepts incomplets qui devront être implémentés dans les sous classes

 factoriser le code
 les opérations abstraites sont particulièrement utiles pour mettre en œuvre le polymorphisme.

 l'utilisation du nom d'une classe abstraite comme type pour une (des) référence(s) est toujours
possible (et souvent souhaitable !!!)
© Philippe GENOUD UGA Décembre 2017 25
Classes abstraites
 classe abstraite :
classe non instanciable, c'est à dire qu'elle n'admet pas
d'instances directes.
 Impossible de faire new ClasseAbstraite(…);
 mais une classe abstraite peut néanmoins avoir un ou des constructeurs

 opération abstraite : opération n'admettant pas d'implémentation


 au niveau de la classe dans laquelle elle est déclarée, on ne peut pas dire
comment la réaliser.

 Une classe pour laquelle au moins une opération abstraite est déclarée est une
classe abstraite (l'inverse n'est pas vrai).

public abstract class ClasseA { public abstract class ClasseA {

... ...

public abstract void methodeA();

...
} la classe contient une méthode } la classe ne contient pas de
abstraite => elle doit être méthode abstraite => elle peut
déclarée abstraite être déclarée abstraite
© Philippe GENOUD UGA Décembre 2017 26
Classes abstraites
 Une classe abstraite est une description d'objets destinée à être héritée par
des classes plus spécialisées.

 Pourêtre utile, une classe abstraite doit admettre des classes descendantes
concrètes.

 Toute classe concrète sous-classe d'une classe abstraite doit “concrétiser”


toutes les opérations abstraites de cette dernière.
 elle doit implémenter toutes les méthodes abstraites

 Une
classe abstraite permet de regrouper certaines caractéristiques
communes à ses sous-classes et définit un comportement minimal commun.

 La
factorisation optimale des propriétés communes à plusieurs classes par
généralisation nécessite souvent l'utilisation de classes abstraites.

© Philippe GENOUD UGA Décembre 2017 27


Classes abstraites
Classes abstraites et diagrammes de classes UML

classe abstraite Forme


x : double
y : double
déplacer(x:double, y:double)
périmètre() : double opération abstraite

classe concrète
classe abstraite
(périmètre() est
Rectangle ... FormeCirculaire héritée et non
concrétisée)
largeur : double rayon: double
hauteur : double utile que si spécialisée
périmètre() double
Disque Couronne
opération concrétisée rayonInterne : double
périmètre() double
périmètre() double

© Philippe GENOUD UGA Décembre 2017 28


Classes abstraites
Exemple introductif
public class Forme
abstract { Forme {
class
public class ListeDeFormes { protected double x,y;

public static final int NB_MAX = 30; public Forme(double x, double y) {


private Forme[] tabFormes = new Forme[NB_MAX]; this.x = x;
private int nbFormes = 0; this.y = y;
}
public void ajouter(Forme f) {
if (nbFormes < NB_MAX) public void deplacer(double dx,
tabFormes[nbFormes++] =f double dy) {
} x += dx; y += dy;
}
public void toutDeplacer(double dx,double dy) {
for (int i=0; i < NbFormes; i++) } public abstract double périmètre();
tabFormes[i].deplacer(dx,dy); public abstract double surface();
} }

public double périmètreTotal() {


Le polymorphisme peut
double perimTotal = 0.0;
for (int i=0; i < nbFormes++; i++) être pleinement exploité.
perimTotal += tabFormes[i].périmètre(); Le compilateur sait que
return perimTotal; chaque objet Forme peut
erreur de
}
compilation
calculer son périmètre
}

© Philippe GENOUD UGA Décembre 2017 29


Classes abstraites
public abstract class Magnitude {

public abstract boolean egalA(Magnitude m) ;

public abstract boolean inferieurA(Magnitude m) ;

public boolean superieurA(Magnitude m) {


return !egalA(m) && !inferieurA(m); Magnitude
}
... égalA(obj : Magnitude) : boolean opérations
inférieurA(obj : Magnitude) : boolean abstraites
opérations concrètes
(basées sur les 2 supérieurA(obj : Magnitude) : boolean
opérations abstraites) ...

Date Caractère ... Nombre


chaque sous-classe concrète
admet une implémentation
différente pour égalA() et
inférieurA()
Réel ... Entier

(exemple inspiré du cours GL de D. Bardou, UPMF)

© Philippe GENOUD UGA Décembre 2017 30


Héritage et abstraction
interfaces
Philippe Genoud

©
© Philippe
Philippe GENOUD
GENOUD UGA
UJF Décembre 2017
2009 31
Interfaces
Bill Venners Designing with Interfaces
One Programmer's Struggle to Understand the Interfaces
[Link]
Exemple introductif
abstract class Animal {
...
abstract void talk();
}

class Dog extends Animal { class Bird extends Animal { class Cat extends Animal {
... ... ...
void talk() { void talk() { void talk() {
[Link]("Woof!"); [Link]("Tweet"); [Link]("Meow");
} } }
} } }

Polymorphisme signifie qu’une référence d’un type


En JAVA le polymorphisme est rendu possible par la
(classe) donné peut désigner un objet de n’importe
liaison dynamique (dynamic binding)
quelle sous classe et selon la nature de cet objet
class Interrogator {
produire un comportement différent
static void makeItTalk(Animal subject) {
Animal animal = new Dog();
[Link]();
...
}
animal = new Cat();
}
animal peut être un Chien, un Chat ou JVM décide à l’exécution (runtime) quelle méthode
n’importe quelle sous classe d'Animal invoquer en se basant sur la classe de l’objet
© Philippe GENOUD UGA Décembre 2017 32
Interfaces
Exemple introductif
Comment utiliser Interrogator pour faire parler aussi un CuckooClock ?
Faire rentrer
CuckooClock dans la
hiérarchie Animal ?
abstract class Animal { class Clock {
abstract void talk(); ...
} } Pas d’héritage multiple

class Dog extends Animal {


class Bird extends Animal { class CuckooClock extends Clock {
void talk() { public void talk() {
[Link]("Woof!"); class Cat extends Animal {
void talk() { [Link]("Cuckoo,
} [Link]("Tweet"); cuckoo!");
} void talk() {
} }
[Link]("Meow.");
} }
}
}

class Interrogator { class CuckooClockInterrogator {

static void makeItTalk(Animal subject) { static void makeItTalk(Cuckooclock subject) {


[Link](); [Link]();
} }
} }

Se passer du
polymorphisme ?

© Philippe GENOUD UGA Décembre 2017 33


Interfaces
Exemple introductif
 Les interfaces permettent plus de polymorphisme car avec les interfaces il n’est pas
nécessaire de tout faire rentrer dans une seule famille (hiérarchie) de classes

abstract class Animal {implements Talkative { class Clock {


abstract void talk(); ...
} }
Association de ce type à
différentes classes de la
hiérarchie d’héritage
class Dog extends Animal {
class Bird extends Animal { implements
class CuckooClock extends Talkative
Clock { {
void talk() { public void talk() {
[Link]("Woof!");
void talk() { [Link]("Cuckoo,
} [Link]("Tweet"); cuckoo!");
} } }
} }

class Interrogator {
interface Talkative {
static void makeItTalk(Animal subject)
(Talkative { {
subject)
public void talk();
[Link]();
}
}
}

Définition d’un type


Utilisation de ce type abstrait
abstrait (interface)

© Philippe GENOUD UGA Décembre 2017 34


Interfaces
 Java'sinterface gives you more polymorphism than you can get
with singly inherited families of classes, without the "burden"
of multiple inheritance of implementation.
Bill Venners Designing with Interfaces –
One Programmer's Struggle to Understand the Interface
[Link]

© Philippe GENOUD UGA Décembre 2017 35


Interfaces
déclaration d’une interface
 Une interface est une collection d'opérations utilisée pour spécifier un service
offert par une classe.
 Une interface peut être vue comme une classe 100% abstraite sans attributs
et dont toutes les opérations sont abstraites.
package [Link]; Possibilité
import [Link]; d'implémen-
Une interface non publique tation par
n'est accessible que dans public interface Dessinable { défaut avec
son package public void dessiner(Graphics g); Toutes les méthodes
void effacer(Graphics g); sont abstraites
} Elles sont implicitement
[Link] publiques
Une interface publique
doit être définie dans un
fichier .java de même
nom «interface» interface
Dessinable
opérations abstraites
dessiner(g : Graphics)
effacer(g: Graphics)
© Philippe GENOUD UGA Décembre 2017 36
Interfaces
dans la javadoc
[Link]

© Philippe GENOUD UGA Décembre 2017 37


Interfaces
déclaration d’une interface
 Possibilité de définir des attributs à condition qu’il s’agisse d’attributs de
type primitif
 Ces attributs sont implicitement déclarés comme static final

import [Link];
public interface Dessinable {
public static final int MAX_WIDTH = 1024;
int MAX_HEIGHT = 768;
public void dessiner(Graphics g);
void effacer(Graphics g);
}

[Link]

© Philippe GENOUD UGA Décembre 2017 38


Interfaces
"réalisation" d’une interface
 Une interface est destinée à être “réalisée” (implémentée) par d’autres classes (celles-ci en
héritent toutes les descriptions et concrétisent les opérations abstraites).
 Les classes réalisantes s'engagent à fournir le service spécifié Forme
par l'interface double x,y; //centre du cercle
Forme (double x, y)
double surface()
 L’implémentation d’une interface est libre. double périmètre()
<< interface >>
 il n'existe pas nécessairement de relations Dessinable
deplacer(double dx,dy)
entre les différentes classes dessiner(Graphics g)
d'implémentation effacer(Graphics g)
Rectangle
double largeur, hauteur;
Clock Rectangle(double x,y,l,h)
… double surface()
double périmètre();

TexteDessinable
CuckooClock
String txt; réalisation
int x,y; RectangleDessinable

Font f; Color c
dessiner(Graphics g)
... opérations RectangleDessinable(double x,y,l,h ,
effacer(Graphics g);
dessiner(Graphics g) concrétisées Color c)
… dessiner(Graphics g)
effacer(Graphics g);
… effacer(Graphics g)

© Philippe GENOUD UGA Décembre 2017 39


Interfaces
"réalisation" d’une interface
 De la même manière qu'une classe étend sa super-classe elle peut de manière
optionnelle implémenter une ou plusieurs interfaces
 dans la définition de la classe, après la clause extends Forme
nomSuperClasse, faire apparaître explicitement le mot clé double x,y; //centre du cercle
implements suivi du nom de l'interface implémentée Forme (double x, y)
double surface()
class RectangleDessinable extends Rectangle implements Dessinable { double périmètre()
private Color c; deplacer(double dx,dy)

public RectangleDessinable(double x, double y, << interface >>


double l, double h, Color c) { Dessinable
super(x,y,l,h); dessiner(Graphics g) Rectangle
this.c = c;
effacer(Graphics g) double largeur, hauteur;
}
Rectangle(double x,y,l,h)
public void dessiner(Graphics g){ double surface()
[Link]((int) x, (int) y, (int) largeur, (int) hauteur); double périmètre();
}
public void effacer(Graphics g){
[Link]((int) x, (int) y, (int)largeur, (int) hauteur);
} RectangleDessinable
} Color c
RectangleDessinable(double x,y,l,h ,
 si la classe est une classe concrète elle doit fournir une Color c)
implémentation (un corps) à chacune des méthodes abstraites dessiner(Graphics g)
définies dans l'interface (qui doivent être déclarées publiques) effacer(Graphics g)

© Philippe GENOUD UGA Décembre 2017 40


Interfaces
"réalisation" d’une interface
 Une classe JAVA peut implémenter simultanément plusieurs interfaces

 la liste des noms des interfaces à implémenter séparés par des Forme
virgules doit suivre le mot clé implements double x,y; //centre du cercle
Forme (double x, y)
class RectangleDessinable extends Rectangle double surface()
implements Dessinable , Enregistrable { double périmètre()
private Color c; deplacer(double dx,dy)

public RectangleDessinable(double x, double y, << interface >>


double l, double h, Color c) { Dessinable
super(x,y,l,h); dessiner(Graphics g) Rectangle
this.c = c; effacer(Graphics g) double largeur, hauteur;
} Rectangle(double x,y,l,h)
public void dessiner(Graphics g){ double surface()
[Link]((int) x, (int) y, (int) largeur, (int) hauteur); double périmètre();
}
public void effacer(Graphics g){
[Link]((int) x, (int) y, (int)largeur, (int) hauteur);
} RectangleDessinable
Color c
public void enregistrer(File f) { RectangleDessinable(double x,y,l,h ,
...
<< interface >> Color c)
} Enregistrable dessiner(Graphics g)
enregistrer(File f) effacer(Graphics g)
} enregistrer(File f)
© Philippe GENOUD UGA Décembre 2017 41
Interfaces
"réalisation" d’une interface
 pour éviter des redéfinitions de méthodes penser à mettre des
directives @Override lorsque implémentation des méthodes
d'une interface Forme
double x,y; //centre du cercle
Forme (double x, y)
class RectangleDessinable extends Rectangle
double surface()
implements Dessinable , Enregistrable {
private Color c; double périmètre()
deplacer(double dx,dy)
public RectangleDessinable(double x, double y,
double l, double h, Color c) { << interface >>
super(x,y,l,h); Dessinable
this.c = c; dessiner(Graphics g) Rectangle
} effacer(Graphics g) double largeur, hauteur;
@Override Rectangle(double x,y,l,h)
public void dessiner(Graphics g){ double surface()
[Link]((int) x, (int) y, (int) largeur, (int) hauteur); double périmètre();
}
@Override
public void effacer(Graphics g){
[Link]((int) x, (int) y, (int)largeur, (int) hauteur);
RectangleDessinable
}
Color c
@Override RectangleDessinable(double x,y,l,h ,
<< interface >> Color c)
public void enregistrer(File f) {
... Enregistrable dessiner(Graphics g)
} enregistrer(File f) effacer(Graphics g)
enregistrer(File f)
} © Philippe GENOUD UGA Décembre 2017 42
Interfaces
Interface et polymorphisme
 Une interface peut être utilisée comme un type
 A des variables (références) dont le type est une interface il est possible d'affecter
des instances de toute classe implémentant l'interface, ou toute sous-classe d'une
telle classe.
public class ZoneDeDessin { Dessinable d;
private nbFigures; ..
private Dessinable[] figures; d = new RectangleDessinable(…);
... ...
public void ajouter(Dessinable d){ [Link](g);
... [Link]();
}
public void supprimer(Dessinable o){
permet de s’intéresser uniquement à
...
} certaines caractéristiques d’un objet

public void dessiner() { règles du polymorphisme s’appliquent de la


for (int i = 0; i < nbFigures; i++) même manière que pour les classes :
figures[i].dessiner(g); • vérification statique du code
}
• liaison dynamique
}

© Philippe GENOUD UGA Décembre 2017 43


Interfaces
héritage d’interface
 De la même manière qu'une classe peut avoir des sous-classes, une interface peut avoir
des "sous-interfaces"
 Une sous interface

 hérite de toutes les méthodes abstraites et des constantes de sa "super-interface"

 peut définir de nouvelles constantes et méthodes abstraites

Types génériques (ou types


??? paramétrés). On verra cela
<< interface >>
Collection<E> dans un cours ultérieur.

interface Set<E> extends Collection<E> {


...
<< interface >> << interface >>
List<E> Set<E>
}

<< interface >>


SortedSet<E>

 Une classe qui implémente une interface doit implémenter toutes les méthodes
abstraites définies dans l'interface et dans les interfaces dont elle hérite.

© Philippe GENOUD UGA Décembre 2017 44


Interfaces
héritage d’interfaces

 A la différence des classes une interface peut


<< interface >>
étendre plus d'une interface à la fois Chanel

boolean isOpen()
void close()
représente une connexion ouverte vers une entité
telle qu’un dipositif hardware, un fichier, une “socket”
réseau, ou tout composant logiciel capable de
réaliser une ou plusieurs opérations d’entrée/sortie.
<< interface >> << interface >>
ReadableByteChanel WritableByteChanel

int read(ByteBuffer dst) int write(ByteBuffer src)

<< interface >>


ByteChanel

package [Link];
interface ByteChannel extends ReadableByteChanel, WriteableByteChanel {
}

© Philippe GENOUD UGA Décembre 2017 45


Interfaces
interêt

 Lesinterfaces permettent de s ’affranchir d ’éventuelles contraintes


d’héritage.
 Lorsqu’on examine une classe implémentant une ou plusieurs
interfaces, on est sûr que le code d’implémentation est dans le corps
de la classe. Excellente localisation du code (défaut de l’héritage
multiple, sauf si on hérite de classes purement abstraites).

 Permet une grande évolutivité du modèle objet

© Philippe GENOUD UGA Décembre 2017 46


Interfaces
interêt
« Smarter Java development » Michael Cymerman , javaworld août 99.
[Link]

 By incorporating interfaces into your next project, you will notice benefits throughout
the lifecycle of your development effort. The technique of coding to interfaces rather
than objects will improve the efficiency of the development team by:

 Allowing the development team to quickly establish the interactions among the
necessary objects, without forcing the early definition of the supporting objects
 Enabling developers to concentrate on their development tasks with the knowledge
that integration has already been taken into account
 Providing flexibility so that new implementations of the interfaces can be added into
the existing system without major code modification
 Enforcing the contracts agreed upon by members of the development team to ensure
that all objects are interacting as designed

© Philippe GENOUD UGA Décembre 2017 47


Evolution des interfaces
 Quand on définit des interfaces il faut être prudent : tout ajout ultérieur
"brise" le code des classes qui implémentent l'interface.
<< interface >>
Dessinable

dessiner(Graphics g)
effacer(Graphics g)
dessiner(Graphics G, Color c)

Clock

CuckooClock TexteDessinable

… String txt;
dessiner(Graphics g) int x,y;
effacer(Graphics g); Font f; ...
… …
dessiner(Graphics g)
effacer(Graphics g);

Ces classes n'implémentent plus l'interface


© Philippe GENOUD UGA Décembre 2017 48
Evolution des interfaces
 Quand on définit des interfaces il faut être prudent : tout ajout ultérieur
"brise" le code des classes qui implémentent l'interface.
<< interface >>
Dessinable

dessiner(Graphics g)
effacer(Graphics g)
dessiner(Graphics G, Color c)

Clock

1ère solution :
CuckooClock TexteDessinable Modifier le code de toutes les classes
… String txt; implémentant l'interface
dessiner(Graphics g) int x,y; (encore faut-il le pouvoir)
effacer(Graphics g); Font f; ...
dessiner(Graphis g, …
Color
… c) dessiner(Graphics g)
effacer(Graphics g);
dessiner(Graphics g,
Color c)

© Philippe GENOUD UGA Décembre 2017 49


Evolution des interfaces
 Quand on définit des interfaces il faut être prudent : tout ajout ultérieur
"brise" le code des classes qui implémentent l'interface.
<< interface >>
Dessinable

dessiner(Graphics g)
effacer(Graphics g)

Clock
… <<interface>>
DessinableColoriable

dessiner(Graphics g , Color c)
CuckooClock TexteDessinable

… String txt; 2ème solution :


dessiner(Graphics g) int x,y;
effacer(Graphics g); Font f; ... Définir une sous interface
… …
dessiner(Graphics g)
effacer(Graphics g);

© Philippe GENOUD UGA Décembre 2017 50


Evolution des interfaces
 Quand on définit des interfaces il faut être prudent : tout ajout ultérieur
"brise" le code des classes qui implémentent l'interface.
<< interface >>
Dessinable

dessiner(Graphics g) 3ème solution :Définir une


effacer(Graphics g) méthode
dessiner(Graphics G, Color c)
par défaut

Clock

CuckooClock TexteDessinable

… String txt;
dessiner(Graphics g) int x,y;
effacer(Graphics g); Font f; ...
… …
dessiner(Graphics g)
effacer(Graphics g);

© Philippe GENOUD UGA Décembre 2017 51


Java 8: quoi de neuf dans les interfaces ? *

 Java7-
 une méthode déclarée dans une interface ne fournit pas d'implémentation

 Ce n'est qu'une signature, un contrat auquel chaque classe dérivée doit se


conformer en fournissant une implémentation propre

 Java 8 relaxe cette contrainte, possibilité de définir


 des méthodes statiques

 des méthodes par défaut

 des interface fonctionnelles

* titre inspiré du titre de l'article Java 8 : du neuf dans les interfaces ! du blog d'Olivier Croisier
[Link]

© Philippe GENOUD UGA Décembre 2017 52


Interfaces Java 8 : méthodes par défaut
 déclaration d'une méthode par défaut
 fournir un corps à la méthode public interface Foo {
public default void foo() {
 qualifier la méthode avec le [Link]("Default implementation of foo()");
mot clé default }
}

 les classes filles sont libérées de fournir une implémentation d'une méthode default, en
cas d'absence d'implémentation spécifique c'est la méthode par défaut qui est invoquée
public interface Itf { public class Cls implements Itf {

/** Pas d'implémentation - comme en Java 7 @Override


et antérieur */ public void foo() {
public void foo(); [Link]("Cls -> foo()");
}
public default void bar() {
[Link]("Itf -> bar() [default]"); @Override
} public void bar() {
[Link]("Cls -> bar()");
public default void baz() { }
[Link]("Itf -> baz() [default]"); }
}
}
Cls cls = new Cls();
[Link]();  Cls -> foo()
[Link]();  Cls -> bar()
[Link]();  Itf -> baz() [default]

© Philippe GENOUD UGA Décembre 2017 53


Interfaces Java 8 : méthodes par défaut

 mais qu'en est-il de l'héritage en diamant ?

public interface InterfaceA { public interface InterfaceB {


public default void foo() { public default void foo() {
[Link]("A -> foo()"); [Link]("B -> foo()");
} }
} }

public class Cls implements InterfaceA, InterfaceB {


Erreur de compilation
"class Test inherits unrelated defaults for foo() from types
} InterfaceA and InterfaceB"
Pour résoudre le conflit, une seule
solution : implémenter la méthode au
niveau de la classe elle-même, car
l'implémentation de la classe est
Cls cls = new Cls(); toujours prioritaire.
? [Link](); ?

public class Cls implements InterfaceA, InterfaceB {


public void foo() {
[Link]("Test -> foo()");
}
}
© Philippe GENOUD UGA Décembre 2017 54
Interfaces Java 8 : méthodes par défaut

 mais qu'en est-il de l'héritage en diamant ?

public interface InterfaceA { public interface InterfaceB {


public default void foo() { public default void foo() {
[Link]("A -> foo()"); [Link]("B -> foo()");
} }
} }

public class Cls implements InterfaceA, InterfaceB {


public
publicclass
void Cls
foo()implements
{ InterfaceA, InterfaceB {
Erreur de compilation
[Link]("Test
[Link](); -> foo()");
} "class Test inherits unrelated defaults for foo() from types
}
} InterfaceA and InterfaceB"
Possibilité d'accéder sélectivement aux implémentations par défaut :
[Link].méthode

Cls cls = new Cls();


[Link]();

© Philippe GENOUD UGA Décembre 2017 55


Evolution des interfaces
 Quand on définit des interfaces il faut être prudent : tout ajout ultérieur
"brise" le code des classes qui implémentent l'interface.
<< interface >>
Dessinable

dessiner(Graphics g) 3ème solution :Définir une


effacer(Graphics g) méthode
dessiner(Graphics G, Color c)
par défaut
import [Link];
Clock import [Link];

interface Dessinable {
void dessiner(Graphics g);
void effacer(Graphics g);
CuckooClock TexteDessinable default void dessiner(Graphics g, color c) {
[Link]();
dessiner(g);
… String txt;
}
dessiner(Graphics g) int x,y;
}
effacer(Graphics g); Font f; ...
… …
dessiner(Graphics g)
effacer(Graphics g);

© Philippe GENOUD UGA Décembre 2017 56

Vous aimerez peut-être aussi