Cours JAVA : Le polymorphisme en Java.

publicité
Grandes lignes du cours
Cours JAVA :
Le polymorphisme en Java.
Version 3.05
Julien Sopena1
1 [email protected]
Équipe REGAL - INRIA Rocquencourt
LIP6 - Université Pierre et Marie Curie
Licence professionnelle DANT - 2013/2014
J. Sopena (INRIA/UPMC)
A
B
...
...
A
B
...
...
Le polymorphisme en Java.
1 / 121
Outline
des limites à l’héritage
L’héritage
Redéfinition de méthode de
Principes de l’héritage
classe
Syntaxe de l’héritage en Java
Classes et méthodes
Héritage et visibilité
abstraites
Héritage et construction
Principes des classes
La redéfinition
abstraites
La covariance
Exemple de classe abstraite
Interdire l’héritage
Interfaces
Polymorphisme et héritage
Préambule et définition
Principes du polymorphisme
Déclaration et
Protocoles et polymorphisme
implémentation
Les protocoles standards
Polymorphisme d’interface
Downcasting : la fin du
Classe ou interface ?
polymorphisme.
Composition d’interfaces
Le polymorphisme impose
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
2 / 121
Outline
L’héritage
Principes de l’héritage
Syntaxe de l’héritage en Java
Héritage et visibilité
Héritage et construction
La redéfinition
La covariance
Interdire l’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
L’héritage
Principes de l’héritage
Syntaxe de l’héritage en Java
Héritage et visibilité
Héritage et construction
La redéfinition
La covariance
Interdire l’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
3 / 121
Rappel – principes de la POO
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
4 / 121
Un nouveau principe POO : Héritage
Définition
Le terme héritage désigne le principe selon lequel une classe peut
hériter des caractéristiques (attributs et méthodes) d’autres classes.
1. Encapsulation
I
I
Rapprochement des données (attributs) et traitements
(méthodes)
Protection de l’information (private et public)
Soient deux classes A et B
I
2. Agrégation (et composition)
I
I
Classe A "A UN" Classe B
I
3. Utilisation
I
Relation d’héritage : Classe B "EST UN" Classe A
I
Classe A "UTILISE" Classe B
Exercice : Héritage, Agrégation ou Utilisation ?
I
I
I
I
I
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
5 / 121
Motivation pour un nouveau type de relation
entre classes
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
6 / 121
1. Faire que la classe Animal puisse vraiment représenter tous les
animaux
I
Animal
I
+getNom(): String
I
+manger(...): ...
+dormir(...): ...
I
+reproduire(...): ...
I
Problèmes pour implémenter cette spécification :
I Elle est trop générale (exemple : manger( ) est très différent
suivant les animaux)
I Il manque les services spécifiques à certaines catégories
d’animaux (exemple : voler( ), nager( ), ...)
Le polymorphisme en Java.
Cercle et Ellipse ?
Salle de bains et Baignoire ?
Piano et Joueur de piano ?
Entier et Réel ?
Personne, Enseignant et Étudiant ?
Les mauvaises solutions
Une classe décrit les services (comportements et données) d’un
ensemble d’individus
Exemple : la classe Animal (animation graphique)
J. Sopena (INRIA/UPMC)
A est la super-classe ou classe mère de B
B est la sous-classe ou classe fille de A
accroître l’interface publique (tous les services possibles de
tous les animaux)
ajouter des attributs booléens pour les catégories (isOiseau,
isPoisson, ...) ou un attribut qui indique la catégorie
tester les attributs pour savoir si on peut répondre à un
message
Exemple : Animal unChat = new Animal ("chat",...); (avec un
attribut genreAnimal de type String dans la classe Animal)
code très complexe et non maintenable
2. Faire autant de classes qu’il existe d’espèces animales
I
I
7 / 121
beaucoup de services vont être très similaires entre les classes
beaucoup de factorisations perdues
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
8 / 121
Classification hiérarchisée
Héritage
Animal
Vertébré
Une sous-classe hérite des services (comportements et
données) de ses ascendants
I
Pour factoriser au mieux la programmation, il suffit de placer
les services à la bonne place dans la relation d’héritage
setNom()
getNom() Animal
Reptile
Poisson
Mammifère
Homme
Invertébré
I
remuerVertèbres()Vertébré
Chat
I
Les sous-classes (spécialisations) de la classe Mammifère sont
les classes Homme et Chat
I
Les ascendants (généralisations) de la classe Mammifère sont
les classes Vertébré et Animal
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
allaiter()Mammifère
écrire() Homme
9 / 121
Hiérarchie en Java
Une classe hérite toujours d’une seule et unique classe
(héritage simple versus héritage multiple)
I
Cette classe est dite super-classe de la sous-classe
I
Par défaut, toute classe hérite de la classe Object qui est la
racine unique de l’arbre d’héritage
Object
Animal
Vertébré
J. Sopena (INRIA/UPMC)
Poisson nager()
Chat
Le polymorphisme en Java.
10 / 121
Outline
I
Mammifère
J. Sopena (INRIA/UPMC)
Invertébré
Poisson
Question
...
Invertébré
L’héritage
Principes de l’héritage
Syntaxe de l’héritage en Java
Héritage et visibilité
Héritage et construction
La redéfinition
La covariance
Interdire l’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
Reptile
Le polymorphisme en Java.
11 / 121
Syntaxe
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
12 / 121
Spécialisation
Pour indiquer qu’une classe hérite d’une autre classe, on utilise le
mot-clé extends.
p u b l i c class Logement {
f i n a l p u b l i c double s u r f a c e ;
p u b l i c double p r i x ;
public S t r i n g p r o p r i e t a i r e ;
p r i v a t e boolean vendu ;
}
p u b l i c class Appartement extends Logement
p u b l i c class Appartement extends Logement {
f i n a l public i n t etage ;
p r i v a t e boolean c a v e ;
}
Important
La classe Appartement ainsi définie possède toutes les caractéristiques de la classe Logement (i.e., ses éléments privés et publics).
Les attributs de la classe Appartement sont : surface, prix,
proprietaire, vendu, etage et cave.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
13 / 121
Implémentation en Java
14 / 121
Durant l’exécution, l’instruction :
unHomme . setNom ( "Adam" ) ;
provoque :
Homme unHomme = new Homme ( . . . ) ;
// a p p e l d ’ un s e r v i c e p r o p r e aux hommes
unHomme . é c r i r e ( ) ;
// a p p e l d ’ un s e r v i c e commun aux v e r t é b r é s ( h é r i t é )
unHomme . r e m u e r V e r t è b r e s ( ) ;
// a p p e l d ’ un s e r v i c e commun aux animaux ( h é r i t é )
unHomme . setNom ( "Adam" ) ;
Le polymorphisme en Java.
Le polymorphisme en Java.
Héritage de comportements
p u b l i c class Homme extends Mammifère {
// a t t r i b u t s p r o p r e s aux hommes u n i q u e m e n t
p r i v a t e boolean d r o i t i e r ;
...
p u b l i c void é c r i r e ( ) {
i f d r o i t i e r { . . . } else { . . . }
}
}
J. Sopena (INRIA/UPMC)
J. Sopena (INRIA/UPMC)
I
La recherche de setNom() dans la classe Homme
I
Puisqu’elle n’existe pas, la recherche se poursuit en remontant
l’arbre d’héritage jusqu’à trouver Animal.setNom()
I
Animal.setNom() est exécutée (dans le contexte de unHomme)
Si la méthode Animal.setNom() n’était pas définie, une erreur
serait détectée lorsque la classe Object serait atteinte
15 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
16 / 121
À retenir : le mot-clé super
À retenir : la classe Object
Important
En Java, toutes les classes héritent de la classe Object.
Á retenir
Java fournit la référence super qui désigne pour chaque classe,
sa classe mère.
La déclaration
p u b l i c class A { . . . }
doit donc être comprise comme
p u b l i c class A extends O b j e c t { . . . }
même si on ne l’écrit pas ainsi.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
17 / 121
Héritage d’attributs
Le polymorphisme en Java.
18 / 121
Héritage d’attributs – suite
p u b l i c class Animal {
// a t t r i b u t s p r o p r e s à t o u s l e s animaux
p r i v a t e S t r i n g nom ; . . .
p u b l i c S t r i n g getNom ( ) { r e t u r n nom ; }
p u b l i c void setNom ( S t r i n g n ) { nom = n ; }
...
}
p u b l i c class V e r t é b r é extends Animal {
// a t t r i b u t s p r o p r e s aux V e r t é b r é s
private int nbVertèbres ; . . .
p u b l i c void s e t N b V e r t è b r e s ( i n t n ) {
nbVertèbres = n ;
}
p u b l i c void r e m u e r V e r t è b r e s ( ) {
System . o u t . p r i n t l n ( this.getNom() + " remue "
+ nbVertèbres + " vertèbres " ) ;
}
}
J. Sopena (INRIA/UPMC)
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
p u b l i c class Homme extends Mammifère {
// a t t r i b u t s p r o p r e s aux hommes u n i q u e m e n t
p r i v a t e boolean d r o i t i e r ;
...
p u b l i c Homme ( S t r i n g unNom , boolean d r o i t i e r ) {
this.setNbVertebres(50) ;
this.setNom(unNom) ;
this . d r o i t i e r = d r o i t i e r ;
}
...
}
19 / 121
Héritage d’attributs – fin
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
20 / 121
Outline
L’héritage
Principes de l’héritage
Syntaxe de l’héritage en Java
Héritage et visibilité
Héritage et construction
La redéfinition
La covariance
Interdire l’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
Homme uneFemme = new Homme( "È v e " , t r u e ) ;
uneFemme
Ève
true
50
uneFemme . r e m u e r V e r t è b r e s ( ) ;
System . o u t . p r i n t l n ( uneFemme . getNom ( ) ) ;
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
21 / 121
Héritage et encapsulation
I
Les membres (attributs et méthodes) déclarés privés dans une
classe ne sont pas visibles dans une sous-classe
I
En d’autres termes, l’héritage n’implique pas la visibilité
Le polymorphisme en Java.
Le polymorphisme en Java.
22 / 121
Visibilité
Le modificateur qui précède chaque méthode (et attribut)
détermine sa visibilité :
la classe elle-même
une sous-classe, paquetage =
pas une sous-classe, paquetage =
une sous-classe, paquetage 6=
pas une sous-classe, paquetage 6=
p u b l i c class Homme extends Mammifère {
// a t t r i b u t s p r o p r e s aux hommes u n i q u e m e n t
p r i v a t e boolean d r o i t i e r ;
...
p u b l i c Homme ( S t r i n g unNom , boolean d r o i t i e r ) {
this . setNbVertebres (50);
nom = unNom ; // e r r e u r
this . d r o i t i e r = d r o i t i e r ;
}
...
}
J. Sopena (INRIA/UPMC)
J. Sopena (INRIA/UPMC)
private
défaut
protected
public
OUI
NON
NON
NON
NON
OUI
OUI
OUI
NON
NON
OUI
OUI
OUI
OUI
NON
OUI
OUI
OUI
OUI
OUI
Rappel
Les attributs doivent toujours être déclarés private
23 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
24 / 121
Outline
Instantiation des attributs hérités
p u b l i c class Homme extends Mammifère {
// a t t r i b u t s p r o p r e s aux hommes u n i q u e m e n t
p r i v a t e boolean d r o i t i e r ;
...
p u b l i c Homme ( S t r i n g unNom , boolean d r o i t i e r ) {
this.setNbVertèbres(50) ;
this.setNom(unNom) ;
this . d r o i t i e r = d r o i t i e r ;
}
...
}
L’héritage
Principes de l’héritage
Syntaxe de l’héritage en Java
Héritage et visibilité
Héritage et construction
La redéfinition
La covariance
Interdire l’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
J. Sopena (INRIA/UPMC)
Problèmes
Le polymorphisme en Java.
25 / 121
Héritage et construction – Correction
I
Obligation d’introduire des modificateurs telles que
Vertébré.setNbVertèbres()
I
Redondance – la super-classe Mammifère doit avoir un
constructeur
J. Sopena (INRIA/UPMC)
Règles
p u b l i c class Homme extends Mammifère {
p r i v a t e s t a t i c f i n a l i n t NB_VERTEBRES = 5 0 ;
p r i v a t e boolean d r o i t i e r ;
1. L’appel d’un constructeur de la classe mère doit être la
première instruction du constructeur de la classe fille.
2. Il n’est pas possible d’utiliser à la fois un autre constructeur
de la classe et un constructeur de sa classe mère dans la
définition d’un de ses constructeurs.
p u b l i c Homme ( S t r i n g unNom , boolean d r o i t i e r ,
int nbVertèbres ) {
// s u p e r d o i t ê t r e l a p r e m i è r e i n s t r u c t i o n
super ( unNom , n b V e r t è b r e s ) ;
this . d r o i t i e r = d r o i t i e r ;
}
p u b l i c class A {
p u b l i c A( i n t x ) {
super ( ) ;
this ( ) ;
}
}
p u b l i c Homme ( S t r i n g unNom , boolean d r o i t i e r ) {
t h i s ( unNom , d r o i t i e r , NB_VERTEBRES ) ;
}
IT
D
ER
T
}
Le polymorphisme en Java.
26 / 121
Règles d’utilisation d’un constructeur de la classe
mère.
Pour initialiser les attributs hérités, le constructeur d’une classe
peut invoquer un des constructeurs de la classe mère à l’aide du
mot-clé super.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
27 / 121
Constructeur implicite
IN
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
28 / 121
Constructeur implicite : exemple
Si aucun constructeur de la classe ou de la super-classe n’est
invoqué explicitement, le compilateur ajoute un appel au
constructeur sans argument de la super-classe
p u b l i c class A {
p u b l i c A ( ) { System . o u t . p r i n t l n ( "A" ) ; } }
p u b l i c class B extends A {
p u b l i c B ( ) { System . o u t . p r i n t l n ( "B" ) ; } }
p u b l i c class B extends A {
p u b l i c B( i n t x ) {
// a p p e l s u p e r ( ) i m p l i c i t e
this . x = x ;
...
}
}
Le ligne de code suivante :
B c = new B ( ) ;
produira l’affichage suivant :
java MonProg
A
B
Attention : Dans ce cas, le constructeur sans argument doit être
défini dans la super-classe
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
29 / 121
Constructeur implicite : erreur fréquente
Etape 1 :
Jusqu’ici tout va bien.
p u b l i c class A {
public i n t x ;
}
p u b l i c class B extends A {
public i n t y ;
public B ( i n t x , i n t y ) {
this . x = x ;
this . y = y ;
}
}
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
30 / 121
Constructeur implicite : erreur fréquente
Etape 2 :
Puis, on ajoute un constructeur.
p u b l i c class A {
public i n t x ;
public A (int x) {
this.x =x;
}
}
p u b l i c class B extends A {
public i n t y ;
public B ( i n t x , i n t y ) {
this . x = x ;
this . y = y ;
}
}
Le polymorphisme en Java.
J. Sopena (INRIA/UPMC)
31 / 121
javac B.java
B.java:3: cannot find symbol
symbol : constructor A()
location: class A
public B ( int x , int y ) {
^
1 error
}
p u b l i c class B extends A {
public i n t y ;
public B ( i n t x , i n t y ) {
super() ;
\\ A j o u t du c o m p i l a t e u r
this . x = x ;
this . y = y ;
}
}
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
32 / 121
Constructeur implicite : Solutions
Solution 1 :
Ajout d’un constructeur vide.
p u b l i c class A {
public i n t x ;
public A () {}
public A ( i n t x ) {
this . x = x ;
}
}
Solution 2 :
Appel explicite au super(int).
p u b l i c class B extends A {
public i n t y ;
public B ( i n t x , i n t y ) {
super(x);
this . y = y ;
}
}
Le polymorphisme en Java.
Un constructeur d’une classe dérivée commence toujours :
1. soit par l’appel explicite d’un autre constructeur de la classe.
2. soit par l’appel explicite ou implicite d’un constructeur de la
classe mère.
p u b l i c class A {
public i n t x ;
public A ( i n t x ) {
this . x = x ;
}
}
p u b l i c class B extends A {
public i n t y ;
public B ( i n t x , i n t y ) {
this . x = x ;
this . y = y ;
}
}
J. Sopena (INRIA/UPMC)
Constructeur d’une classe dérivée
33 / 121
Outline
Corollaire
Comme tout objet dérive (directement ou indirectement) de la
classe Object : Tout constructeur commence par exécuter
le constructeur de l’Object
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
34 / 121
Définition de la redéfinition.
Définition
L’héritage
Principes de l’héritage
Syntaxe de l’héritage en Java
Héritage et visibilité
Héritage et construction
La redéfinition
La covariance
Interdire l’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
On appelle redéfinition (en anglais « overriding ») d’une méthode,
la possibilité de définir le comportement d’une méthode selon le
type d’objet l’invoquant, i.e., de donner une nouvelle
implémentation à une méthode héritée sans changer sa signature.
p u b l i c class
public i n t
...
}
}
p u b l i c class
public i n t
...
}
}
35 / 121
La signature d’une méthode Java
37 / 121
Le polymorphisme en Java.
36 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
38 / 121
Spécialiser une méthode héritée
On peut aussi surcharger une méthode redéfinie.
La référence super permet de redéfinir une méthode f héritée en
réutilisant sa définition dans la classe mère. On dit alors qu’on
spécialise la méthode héritée f.
p u b l i c class Logement {
p u b l i c void v e n d r e ( S t r i n g a c q u e r e u r ) {
this . p r o p r i e t a i r e = acquereur ;
t h i s . vendu = t r u e ;
}
}
p u b l i c class A {
p u b l i c void f ( ) {
...
}
}
p u b l i c class Appartement extends Logement {
p u b l i c void v e n d r e ( S t r i n g a c q u e r e u r ) {
this ( acquereur ) ;
this . cave = false :
}
p u b l i c void v e n d r e ( S t r i n g a c q u e r e u r , boolean c a v e ) {
this ( acquereur ) ;
this . cave = cave :
}
}
Le polymorphisme en Java.
J. Sopena (INRIA/UPMC)
Il ne faut pas confondre la redéfinition (en anglais « overriding »)
et la surcharge (en anglais « overloading ») qui a été étudiée
dans le cours d’introduction et qui correspond à la possibilité de
définir des comportements différents pour la même méthode selon
les arguments passés en paramètres.
Surcharge d’une méthode redéfinie
J. Sopena (INRIA/UPMC)
B extend A {
f (int x) {
ATTENTION
p u b l i c class L e o n a r d extends Homme {
...
p u b l i c void dessiner () {
System . o u t . p r i n t l n ( " J o c o n d e " ) ;
}
}
Le polymorphisme en Java.
{
Overloading vs Overriding
p u b l i c class Homme extends Mammifère {
...
p u b l i c void dessiner () {
System . o u t . p r i n t l n ( " G r i b o u i l l i s " ) ;
}
}
J. Sopena (INRIA/UPMC)
A {
f (int x)
p u b l i c class B extends A {
p u b l i c void f ( ) {
...
super.f()
...
}
}
39 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
40 / 121
Spécialiser une méthode héritée : exemple
Limite pour désigner une méthode redéfinie
p u b l i c class P o i n t {
private int x , y ;
...
public S t r i n g t o S t r i n g ( ) {
return " ( " + x + " , " + y + " ) " ;
}
}
Attention
On ne peut remonter plus haut que la classe mère pour récupérer
une méthode redéfinie :
p u b l i c class P o i n t C o u l e u r extends P o i n t {
p r i v a t e byte c o u l e u r ;
...
public S t r i n g t o S t r i n g ( ) {
r e t u r n super . t o S t r i n g ( ) +
"\ nCouleur ␣ : ␣" + t h i s . c o u l e u r ;
}
}
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
41 / 121
Annotation pour la redéfinition
I
pas de cast (ClasseAncetre)m()
I
pas de super.super.m()
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
42 / 121
Outline
Depuis Java 5, on peut annoter par @Override les redéfinitions de
méthodes. Ceci est très utile pour repérer des fautes de frappe dans
le nom de la méthode : le compilateur envoie un message d’erreur si
la méthode ne redéfinit aucune méthode.
p u b l i c class P o i n t {
private int x , y ;
...
@Override
public S t r i n g t o s t r i n g ( ) {
return " ( " + x + " , " + y + " ) " ;
}
}
L’héritage
Principes de l’héritage
Syntaxe de l’héritage en Java
Héritage et visibilité
Héritage et construction
La redéfinition
La covariance
Interdire l’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
Point.java:3: method does not override or implement a method from a
supertype
@Override
ˆ
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
43 / 121
Les fondements de la covariance
2. La signature d’une méthode est composée de son nom et
des types de ses arguments.
Définition
On appelle covariance le fait de modifier le type de retour d’une
méthode lors de sa redéfinition. En Java, elle a été introduite dans
la version : Java 1.5.
45 / 121
classes finales
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
46 / 121
Méthodes finales
On peut empêcher la redéfinition d’une méthode d’instance d’une
classe dans une de ses sous-classes en la déclarant final.
Lors de la conception d’une classe, le concepteur peut empêcher
que d’autres classes héritent d’elle (classe finale).
p u b l i c class A {
f i n a l p u b l i c void f ( ) {}
}
f i n a l p u b l i c class A { }
Remarque(s)
La classe String est une classe finale.
J. Sopena (INRIA/UPMC)
44 / 121
L’héritage
Principes de l’héritage
Syntaxe de l’héritage en Java
Héritage et visibilité
Héritage et construction
La redéfinition
La covariance
Interdire l’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
1. La redéfinition d’une méthode c’est le fait de donner une
nouvelle implémentation en conservant la signature.
Le polymorphisme en Java.
Le polymorphisme en Java.
Outline
Rappels
J. Sopena (INRIA/UPMC)
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
p u b l i c class B extends A {
// on ne p e u t p a s r e d é f i n i r f ( ) !
}
47 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
48 / 121
Outline
Outline
L’héritage
Polymorphisme et héritage
Principes du polymorphisme
Protocoles et polymorphisme
Les protocoles standards
Downcasting : la fin du polymorphisme.
Le polymorphisme impose des limites à l’héritage
Redéfinition de méthode de classe
Classes et méthodes abstraites
Interfaces
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
L’héritage
Polymorphisme et héritage
Principes du polymorphisme
Protocoles et polymorphisme
Les protocoles standards
Downcasting : la fin du polymorphisme.
Le polymorphisme impose des limites à l’héritage
Redéfinition de méthode de classe
Classes et méthodes abstraites
Interfaces
49 / 121
Polymorphisme : définition
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
50 / 121
Principe POO : Polymorphisme
Si la classe B hérite de la classe A
I
Classe B "EST-UN" Classe A
I
toute méthode m de A peut-être invoquée sur une instance de
la classe B (+ transitivité sur l’héritage de A)
Le polymorphisme consiste à exploiter cela en fournissant un B dans
les expressions "qui attendent" un A.
Définition
Le polymorphisme peut être vu comme la capacité de choisir
dynamiquement la méthode qui correspond au type réel de l’objet.
// un homme e s t un a n i m a l
Animal anim1 = new Homme( " Caïn " , f a l s e ) ;
// un c h a t a u s s i
Animal anim2 = new Chat ( " E u r o p é e n " ) ;
System . o u t . p r i n t l n ( anim1 . getNom ( ) ) ;
System . o u t . p r i n t l n ( anim2 . getNom ( ) ) ;
// un a n i m a l n ’ e s t p a s n é c e s s a i r e m e n t un homme
Homme h = anim1
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
51 / 121
Choix de la méthode : liaison dynamique
p u b l i c s t a t i c void main ( S t r i n g [ ] a r g s ) {
P o i n t [ ] t a b = new P o i n t [ 3 ] ;
t a b [ 0 ] = new PointCouleur ( 2 , 3 , b l e u ) ;
t a b [ 1 ] = new PointCouleur ( 2 , 3 , v e r t ) ;
t a b [ 2 ] = new PointCouleur ( 2 , 3 , r o u g e ) ;
System . o u t . p r i n t l n ( "Ma␣ l i g n e ␣ : ␣ " ) ;
for ( Point p : tab )
System . o u t . p r i n t l n ( " ␣−␣ " + p . toString ( ) ) ;
}
}
}
53 / 121
Choix de la méthode : liaison dynamique (suite)
J. Sopena (INRIA/UPMC)
1. La méthode toString() est définie dans Point
54 / 121
Écrire du code polymorphe : le problème
p u b l i c class Zoo {
p u b l i c s t a t i c void main ( S t r i n g [ ] a r g s ) {
Cage uneCage1 = new Cage ( . . . ) ;
Cage uneCage2 = new Cage ( . . . ) ;
2. Mais elle est spécialisée dans PointCouleur
C’est la version la plus spécialisée (PointCouleur.toString())
qui est invoquée car la recherche de la méthode débute dans la
classe effective de l’objet référencé par p
// On a j o u t e un l i o n
L i o n u n L i o n = new L i o n ( . . . ) ;
uneCage1 . a c c u e i l l i r ( u n L i o n ) ;
La recherche est menée à l’exécution et ce mécanisme est appelé la
liaison dynamique.
Lorsqu’une méthode est spécialisée dans une sous-classe, sa
visibilité peut être augmentée (ex. protected → public) mais elle
ne peut pas être réduite (ex. public 6→ private)
Le polymorphisme en Java.
Le polymorphisme en Java.
On veut coder une classe Zoo qui aura plusieurs cages permettant
d’acceuillir différents types d’animaux. Il faut donc implémenter une
classe Cage permettant de contenir tous ces annimaux.
Si p référence une PointCouleur, quelle méthode toString() va
être invoquée ?
J. Sopena (INRIA/UPMC)
52 / 121
p u b l i c class T r a c e u r D e L i g n e {
p u b l i c class P o i n t C o u l e u r extends P o i n t {
p r i v a t e byte c o u l e u r ;
...
public S t r i n g t o S t r i n g ( ) {
r e t u r n super . t o S t r i n g ( ) +
"\ nCouleur ␣ : ␣" + t h i s . c o u l e u r ;
}
}
Le polymorphisme en Java.
Le polymorphisme en Java.
Choix de la méthode : liaison dynamique (suite)
p u b l i c class P o i n t {
private int x , y ;
...
public S t r i n g t o S t r i n g ( ) {
return " ( " + x + " , " + y + " ) " ;
}
}
J. Sopena (INRIA/UPMC)
J. Sopena (INRIA/UPMC)
;
// On a j o u t e un s i n g e
S i n g e u n S i n g e = new S i n g e ( . . . ) ;
uneCage2 . a c c u e i l l i r ( u n S i n g e ) ;
}
}
55 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
56 / 121
Écrire du code polymorphe : la mauvaise solution
La bonne solution consiste à utiliser le polymorphisme, en
implémentant une méthode acceuillir générique pour tout les
animaux.
p u b l i c class Cage {
p u b l i c void a c c u e i l l i r ( L i o n l ) {
...
}
p u b l i c void a c c u e i l l i r ( S i n g e s ) {
...
}
}
Son paramètre étant de type Animal on pourra l’appeler avec une
référence de Lion ou de Singe.
p u b l i c class Cage {
p u b l i c void a c c u e i l l i r ( Animal a ) {
System . o u t . p r i n t l n ( a . getNom ( ) + " e s t ␣ en ␣ c a g e " ) ;
...
}
}
Ici, la surcharge est une très mauvaise solution
I
Si une nouvelle espèce animale doit être prise en compte, il
faudra modifier le code de la classe Cage
J. Sopena (INRIA/UPMC)
Écrire du code polymorphe : la bonne solution
Le polymorphisme en Java.
57 / 121
Outline
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
58 / 121
Motivation
L’héritage
Polymorphisme et héritage
Principes du polymorphisme
Protocoles et polymorphisme
Les protocoles standards
Downcasting : la fin du polymorphisme.
Le polymorphisme impose des limites à l’héritage
Redéfinition de méthode de classe
Classes et méthodes abstraites
Interfaces
J. Sopena (INRIA/UPMC)
Nouvelle spécification à prendre en compte : tous les animaux ne
peuvent pas aller en cage
La méthode Cage.accueillir() doit être à même de détecter les
animaux ne pouvant l’être
p u b l i c class Zoo {
p u b l i c s t a t i c void main ( S t r i n g [ ] a r g s ) {
Cage uneCage1 = new Cage ( . . . ) ;
Homme unHomme = new Homme ( . . . ) ;
uneCage . a c c u e i l l i r (unHomme ) ; =⇒ il refuse !!!
}
}
Le polymorphisme en Java.
59 / 121
Première solution
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
60 / 121
Mise en place d’un protocole
p u b l i c class Cage {
...
p u b l i c void a c c u e i l l i r ( Animal a ) {
i f ( ! a . supporteCage ( ) ) {
System . o u t . p r i n t ( a . getNom ( ) ) ;
System . o u t . p r i n t l n ( " ␣ r e f u s e ␣d ’ a l l e r ␣ en ␣ c a g e " ) ;
return ;
}
...
}
}
p u b l i c class Cage {
...
p u b l i c void a c c u e i l l i r ( Animal a ) {
i f ( a instanceof Homme )
System . o u t . p r i n t l n ( a . getNom ( )
+ " r e f u s e ␣d ’ a l l e r ␣ en ␣ c a g e " ) ;
return ;
...
}
}
Très mauvaise solution
I
I
Des connaissances propres à la classe Homme sont dans la
classe Cage
si une nouvelle espèce animale refuse d’aller en cage, il faudra
modifier le code de la classe Cage
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
61 / 121
Vue de l’arbre d’héritage
supporteCage()
Vertébré
⇒ true
supporteCage()
Homme
⇒ false
J. Sopena (INRIA/UPMC)
Tout animal doit pouvoir répondre à ce protocole
I
Nous allons implémenter le protocole dans la hiérarchie de
racine Animal, en utilisant l’héritage et en spécialisant lorsque
c’est nécessaire
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
62 / 121
Mise en place d’un protocole
public class Animal {
...
p u b l i c boolean s u p p o r t e C a g e ( ) { r e t u r n f a l s e ; }
}
supporteCage()
Animal
⇒ false
Mammifère
I
Invertébré
supporteCage()
⇒ false
Poisson
p u b l i c c l a s s Homme extends Mammifère {
...
p u b l i c boolean s u p p o r t e C a g e ( ) { r e t u r n f a l s e ; }
}
p u b l i c c l a s s Zoo {
p u b l i c s t a t i c void main ( S t r i n g [ ] a r g s ) {
Cage uneCage1 = new Cage ( . . . ) ;
uneCage1 . a c c u e i l l i r ( new L i o n ( . . . ) ) ;
// G é n è r e un a p p e l à V e r t é b r é . s u p p o r t e C a g e ( ) ;
}
}
Lion
Le polymorphisme en Java.
p u b l i c c l a s s V e r t é b r é extends A n i m a l {
...
p u b l i c boolean s u p p o r t e C a g e ( ) { r e t u r n t r u e ; }
}
63 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
64 / 121
Outline
Retour sur les protocoles standards
p u b l i c c l a s s Zoo {
p u b l i c s t a t i c void main ( S t r i n g [ ] a r g s ) {
Cage [ 1 0 ] l e s C a g e s ;
L i o n u n L i o n = new L i o n ( . . . ) ;
l e s C a g e s [ 0 ] . a c c u e i l l i r ( unLion ) ;
S i n g e u n S i n g e = new S i n g e ( . . . ) ;
lesCages [ 1 ] . a c c u e i l l i r ( unSinge ) ;
L’héritage
Polymorphisme et héritage
Principes du polymorphisme
Protocoles et polymorphisme
Les protocoles standards
Downcasting : la fin du polymorphisme.
Le polymorphisme impose des limites à l’héritage
Redéfinition de méthode de classe
Classes et méthodes abstraites
Interfaces
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
f o r ( Cage c : l e s C a g e s ) {
System . o u t . println(c.contenu()) ;
i f ( u n L i o n . equals(c.contenu())
System . o u t . p r i n t l n ( " J ’ a i ␣ t r o u v e ␣ l e ␣ l i o n " ) ;
}
}
}
65 / 121
Le protocole toString()
p u b l i c c l a s s System {
public s t a t i c PrintStream
...
}
public class PrintStream {
p u b l i c v o i d p r i n t ( Object
I
La classe Lion ne dispose pas de méthode equals(),
pourquoi n’y a-t-il pas d’erreur de compilation ?
I
Où est l’appel la méthode toString() de Animal ?
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
66 / 121
Le protocole toString() – suite
out ;
I
La classe Object est la racine de l’unique arbre d’héritage
I
La classe Animal hérite (implicitement) de la classe Object
I
Il suffit de spécialiser la méthode toString() dans vos classes
pour qu’un objet de type PrintStream (tel que System.out)
puisse afficher vos instances
arg ) {
p r i n t ( a r g . toString() ) ; }
...
p u b l i c class Animal
...
}
{
@Override
public S t r i n g t o S t r i n g ( ) {
r e t u r n t h i s . getNom ( ) ;
}
p u b l i c c l a s s Object {
p u b l i c S t r i n g toString ( ) {
r e t u r n g e t C l a s s ( ) . getName ( ) + "@" + I n t e g e r . t o H e x S t r i n g ( h a s h C o d e ( ) ) ;
}
...
}
}
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
67 / 121
Le protocole equals()
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
68 / 121
Le protocole equals() – suite
Le protocole equals() est employé dans les paquetages standards
pour comparer les objets entre eux Extrait de la documentation de
java.util.Arrays :
La classe Object dispose d’une méthode equals()
p u b l i c s t a t i c boolean e q u a l s ( O b j e c t [ ] a , O b j e c t [ ] a2 )
p u b l i c class Object {
p u b l i c boolean equals ( O b j e c t a r g ) {
r e t u r n t h i s == a r g ;
}
...
}
Returns true if the two specified arrays of Objects are equal to one
another. The two arrays are considered equal if both arrays contain
the same number of elements, and all corresponding pairs of
elements in the two arrays are equal.
Two objects e1 and e2 are considered equal if
Elle ne retourne true que si les deux références désignent le même
objet
( e1==n u l l ? e2==n u l l : e1 . equals ( e2 ) )
In other words, the two arrays are equal if they contain the same
elements in the same order. Also, two array references are
considered equal if both are null.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
69 / 121
Spécialisation de equals() dans vos classes
Le polymorphisme en Java.
Le polymorphisme en Java.
70 / 121
Outline
p u b l i c class C o o r d o n n é e {
private int x , y ;
...
p u b l i c boolean e q u a l s ( O b j e c t o b j ) {
// t e s t s u r l e s r é f é r e n c e s
i f ( t h i s == o b j )
return true ;
i f ( o b j == n u l l )
return false ;
// t e s t s u r l e s c l a s s e s
i f ( this.getClass ( ) != o b j . getClass ( ) )
return false ;
// t e s t s u r l e s d o n n é e s
C o o r d o n n é e o t h e r = (Coordonnée) obj ;
r e t u r n ( t h i s . x == o t h e r . x && t h i s . y == o t h e r . y ) ;
}
}
J. Sopena (INRIA/UPMC)
J. Sopena (INRIA/UPMC)
L’héritage
Polymorphisme et héritage
Principes du polymorphisme
Protocoles et polymorphisme
Les protocoles standards
Downcasting : la fin du polymorphisme.
Le polymorphisme impose des limites à l’héritage
Redéfinition de méthode de classe
Classes et méthodes abstraites
Interfaces
71 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
72 / 121
Upcasting : classe fille → classe mère
Downcasting : classe mère → classe fille
Définition
Définition
On appelle surclassement ou upcasting le fait d’enregistrer une
référence d’une instance d’une classe B héritant d’une classe A dans
une variable de type A. En java, cette opération est implicite et
constitue la base du polymorphisme.
On appelle déclassement ou downcasting le fait de convertir une
référence « surclassée » pour « libérer » certaines fonctionnalités
cachées par le surclassement. En java, cette conversion n’est pas
implicite, elle doit être forcée par l’oppérateur de cast :
(<nomClasse>).
p u b l i c class A { . . . }
p u b l i c class A { . . . }
p u b l i c class B extends A { . . . }
p u b l i c class B extends A { . . . }
A a = new B ( ) // C ’ e s t de l ’ u p c a s t i n g ( s u r c l a s s e m e n t ) .
A a = new B ( ) ; // s u r c l a s s e m e n t , u p c a s t i n g
B b = (B) a ; // d o w n c a s t i n g
On dit que a1 est une référence surclassée (elle est du type A et
contient l’adresse d’une instance d’une sous-classe de A).
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
Pour que la conversion fonctionne, il faut qu’à l’exécution le type
réel de la référence à convertir soit B ou une des sous-classe de B !
73 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
74 / 121
Downcasting : utilisation de instanceof
Downcasting : mise en garde !
On peut utiliser le mot-clé instanceof pour savoir si une référence
d’une classe donnée ou d’une de ces sous-classes.
Attention
Le downcasting ne permet pas de convertir une instance d’une
classe donnée en une instance d’une sous-classe !
Si a est une référence de type B alors l’expression a instanceof A
renvoie true si B est une sous-classe de A et false sinon.
a = new B ( ) ;
i f ( a i n s t a n c e o f A) {
System . o u t . p r i n t
( " a ␣ r é f é r e n c e ␣ un ␣A , " ) ;
System . o u t . p r i n t l n ( " ou ␣ une ␣ s o u s ␣ c l a s s e ␣ de ␣A . " ) ;
}
class A { A ( ) {}}
class B extends A { B ( ) {}}
A a = new A ( ) ;
B b = (B) a ;
Remarque(s)
Attention, l’utilisation d’instanceof est souvent la marque d’un
défaut de conception et va à l’encontre du polymorphisme.
Ça compile, mais ça plantera à l’exécution :
Exception in thread "main" java.lang.ClassCastException:
A cannot be cast to B
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
75 / 121
Exemple : classe rendant un service générique.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
76 / 121
Exemple : polymorphisme d’héritage
public class Garage {
Ve hicu le [ ] tab ;
int nbVehicules ;
p u b l i c class V e h i c u l e {
...
}
Garage ( i n t t a i l l e ) {
t a b = new V e h i c u l e [ t a i l l e ] ;
nbVehicules = 0;
}
p u b l i c class Moto extends V e h i c u l e {
...
}
void e n t r e r V e h i c u l e ( V e h i c u l e v ) {
i f ( n b V e h i c u l e s <t a b . l e n g t h )
t a b [ n b V e h i c u l e s ++] = v ;
}
p u b l i c class V o i t u r e extends V e h i c u l e {
int temperature ;
...
void a u g m e n t e r C h a u f f a g e ( i n t deg ) {
t e m p e r a t u r e += deg ;
}
}
Vehicule sortirVehicule () {
i f ( n b V e h i c u l e s >0)
r e t u r n t a b [−− n b V e h i c u l e s ] ;
else
return null ;
}
}
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
77 / 121
Exemple : le downcast c’est la fin du
polymorphisme
Le polymorphisme en Java.
Le polymorphisme en Java.
78 / 121
Outline
L’héritage
Polymorphisme et héritage
Principes du polymorphisme
Protocoles et polymorphisme
Les protocoles standards
Downcasting : la fin du polymorphisme.
Le polymorphisme impose des limites à l’héritage
Redéfinition de méthode de classe
Classes et méthodes abstraites
Interfaces
p u b l i c class Main {
p u b l i c s t a t i c void main ( S t r i n g [ ] a r g s ) {
I n d i v i d u moi = new I n d i v i d u ( . . . ) ;
G a r a g e monGarage = new G a ra g e ( 2 ) ;
// Le p o l y m o r p h i s m e p e r m e t de g a r e r d e s
// v é h i c u l e s s a n s s ’ o c c u p e r de l e u r s t y p e s .
monGarage . e n t r e r V e h i c u l e (new Moto ( ) ) ;
monGarage . e n t r e r V e h i c u l e (new V o i t u r e ( ) ) ;
...
V e h i c u l e u n V e h i c u l e = monGarage . s o r t i r V e h i c u l e ( ) ;
i f ( moi . a v o i r F r o i d ( ) ) {
// S i on ne p a r t a g e p a s l e g a r a g e , on s a i t
// qu ’ on v i e n t de s o r t i r une v o i t u r e
(( Voiture ) unVehicule ) . augmenterChauffage ( 1 0 ) ;
}
}
}
J. Sopena (INRIA/UPMC)
J. Sopena (INRIA/UPMC)
79 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
80 / 121
Ce qu’on ne peut pas faire et ne pas faire
Problème de la covariance
Pour permettre le polymorphisme :
Dans cet exemple de covariance, peut-on choisir Y librement ?
=⇒ une sous classe doit pouvoir se faire passer pour une sur
classeur ;
p u b l i c class A {
...
public X f ( i n t x ) {
...
}
}
=⇒ une fille doit pouvoir le faire tout ce que fait sa mère ;
On ne peut rien supprimer :
I
On ne peut pas supprimer un membre ;
I
Changer le type d’un attribut ;
I
On ne peut pas réduire la visibilité d’un membre ;
I
La covariance doit maintenir la compatibilité (voir suivants).
p u b l i c class B extends A {
...
@Override
public Y f ( i n t x ) {
...
}
}
Par contre on peut toujours ajouter/modifier des choses :
I
On peut ajouter des membres ;
I
On peut redéfinir des méthodes ;
I
On peut augmenter la visibilité d’un membre.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
81 / 121
Problème de la covariance
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
82 / 121
Limite de la covariance
Dans cet exemple de covariance, peut-on choisir Y librement ?
p u b l i c class Main {
s t a t i c void g (A a ) {
...
X x = a . f (3);
...
}
p u b l i c s t a t i c void main ( S t r i n g [ ] a r g s ) {
A a = new A ( ) ;
g(a );
a = new B ( ) ;
// Q u e l l e v e r s i o n f s e r a e x e c u t é e d a n s c e t a p p e l ?
g(a );
}
}
p u b l i c class A {
...
public X f ( i n t x ) {
...
}
}
p u b l i c class B extends A {
...
@Override
public Y f ( i n t x ) {
...
}
}
C’est la verion de B qui sera executée :
=⇒ La référence de Y retournée doit être "compatible" avec X
=⇒ La classe Y doit être un descendant de de la classe X
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
83 / 121
Limite de la covariance
85 / 121
Overriding vs Hiding
Le polymorphisme en Java.
86 / 121
public class Felide () {
s t a t i c String rugir () {
S y s t e m . o u t . p r i n t l n ( " Miaou ␣ ! ! ! " ) ;
}
}
On appelle en anglais « hiding », la redéfinition d’une méthode
de classe. Son comportement diffère de l’« Overriding » qui est
une redéfinition d’une méthode d’instance.
p u b l i c class Lion () {
s t a t i c String rugir () {
S y s t e m . o u t . p r i n t l n ( "GRRRRRR␣ ! ! ! " ) ;
}
}
Contrairement aux méthodes d’instance, les appels aux méthodes
de classe sont résolus statiquement à la compilation.
p u b l i c c l a s s Savane {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
F e l i d e f = new L i o n ( ) ;
S y s t e m . o u t . p r i n t l n ( " Le ␣ l i o n ␣ f a i t ␣ : ␣ " + f . r u g i r ( ) ) ;
}
}
Si une instance est utilisée pour l’invocation, la classe utilisée sera
celle du type déclaré et non du type réel de l’objet.
=⇒ Il n’y a pas de polymorphisme sur les méthodes de classe
Le polymorphisme en Java.
J. Sopena (INRIA/UPMC)
Tout est décidé statiquement
Définition
J. Sopena (INRIA/UPMC)
84 / 121
L’héritage
Polymorphisme et héritage
Principes du polymorphisme
Protocoles et polymorphisme
Les protocoles standards
Downcasting : la fin du polymorphisme.
Le polymorphisme impose des limites à l’héritage
Redéfinition de méthode de classe
Classes et méthodes abstraites
Interfaces
Lorsque l’on fait de la redéfinition avec covariance, le nouveau
type de retour doit toujours être un sous-type du type de retour
original.
Le polymorphisme en Java.
Le polymorphisme en Java.
Outline
Règle de covariance
J. Sopena (INRIA/UPMC)
J. Sopena (INRIA/UPMC)
87 / 121
java Savane
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
88 / 121
Tout est décidé statiquement
Outline
public class Felide () {
s t a t i c String rugir () {
S y s t e m . o u t . p r i n t l n ( " Miaou ␣ ! ! ! " ) ;
}
}
L’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Principes des classes abstraites
Exemple de classe abstraite
Interfaces
p u b l i c class Lion () {
s t a t i c String rugir () {
S y s t e m . o u t . p r i n t l n ( "GRRRRRR␣ ! ! ! " ) ;
}
}
p u b l i c c l a s s Savane {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
F e l i d e f = new L i o n ( ) ;
S y s t em . o u t . p r i n t l n ( " Le ␣ l i o n ␣ f a i t ␣ : ␣ " + f . r u g i r ( ) ) ;
}
}
java Savane
Le lion fait : Miaou !!!
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
88 / 121
Outline
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
89 / 121
Motivation
p u b l i c class A n i m a t i o n {
...
p u b l i c void f a i r e M a n g e r ( Animal a , N o u r r i t u r e n ) {
...
a . manger ( n ) ;
...
}
...
}
L’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Principes des classes abstraites
Exemple de classe abstraite
Interfaces
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
90 / 121
Spécification d’un protocole sans implémentation
par défaut
I
Il faut introduire une méthode manger() dans la classe Animal
pour que cela compile
I
problème =⇒ quel comportement y décrire puisque la façon de
manger dépend de l’espèce animale ?
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
91 / 121
Méthodes abstraites =⇒ Classe abstraite
Spécification du protocole – le plus haut possible dans l’arbre d’héritage
p u b l i c abstract class Animal {
...
p u b l i c abstract void manger ( N o u r r i t u r e n ) ;
// p a s de c o d e a s s o c i é
...
}
Définition
Un classe contenant au moins une méthode abstraite est appelée
une classe abstraite et cela doit être explicitement précisé dans la
déclaration avec : abstract class
Remarque(s)
Spécialisation du protocole – là où c’est nécessaire dans l’arbre d’héritage
p u b l i c class L i o n extends Mammifère {
...
p u b l i c void manger ( N o u r r i t u r e n ) {
. . . // c o d e s p é c i f i q u e aux l i o n s
}
...
}
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
92 / 121
Classe abstraite : instanciation et spécialisation.
I
I
Une classe abstraite peut contenir des méthodes concrètes.
I
Une classe peut être déclarée abstraite sans contenir de
méthode abstraite.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
93 / 121
Outline
Une classe abstraite constitue un type à part entière :
Animal unAnimal ; // OK
I
Une classe abstraite ne peut pas être instanciée, en effet son
comportement n’est pas complètement défini :
Animal unAnimal = new Animal ( . . . ) ; // ERREUR
I
Une sous-classe d’une classe abstraite peut
implémenter toutes les méthodes abstraites de sa
super-classe. Elle pourra alors être déclarée comme concrète et
donc instanciée.
I ne pas implémenter toutes ces méthodes abstraite. Elle reste
alors nécessairement abstraite ( abstract class ) et ne pourra
être instanciée.
I ajouter d’autre(s) méthode(s) abstraite(s). Elle reste alors
nécessairement abstraite ( abstract class ) et ne pourra être
instanciée.
(INRIA/UPMC)
Le polymorphisme en Java.
94 / 121
L’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Principes des classes abstraites
Exemple de classe abstraite
Interfaces
I
J. Sopena
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
95 / 121
Exemple : besoin
Exemple : déclaration de la classe abstraite.
p u b l i c a b s t r a c t class F i g u r e {
p r i v a t e S t r i n g nom ;
Considérons la hiérarchie de classes suivantes :
aire()
// Une c l a s s e a b s t r a i t e ne p e u t p a s ê t r e i n s t a n c i é e ,
// m a i s e l l e p e u t a v o i r un c o n s t r u c t e u r :
p u b l i c F i g u r e ( S t r i n g nom ) {
t h i s . nom=nom ;
}
Figure
Cercle
// V o i l à l a méthode a b s t r a i t e à c o m p l é t e r :
p u b l i c a b s t r a c t double a i r e ( ) ;
Rectangle
Cahier de charge : on veut que toutes les classes disposent de la
méthode aire() retournant l’aire de la figure géométrique définie
par la classe.
// T o u t e s l e s méthodes ne s o n t p a s a b s t r a i t e s :
public S t r i n g q u i S u i s J e ( ) {
System . o u t . p r i n t l n ( " Je ␣ s u i s ␣ un ␣ " + t h i s . nom ) ;
}
}
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
96 / 121
Exemple : première implémentation.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
97 / 121
Exemple : deuxième implémentation.
p u b l i c class R e c t a n g l e extends F i g u r e {
p r i v a t e double l a r g e u r ;
p r i v a t e double l o n g u e u r ;
p u b l i c class C e r c l e extends F i g u r e {
p r i v a t e double r a y o n ;
p u b l i c C e r c l e ( double r a y o n ) {
super ( " c e r c l e " ) ;
this . rayon = rayon ;
}
p u b l i c R e c t a n g l e ( double l a r g e u r , double l o n g u e u r ) {
super ( " r e c t a n g l e " ) ;
this . largeur = largeur ;
this . longueur = longueur ;
}
p u b l i c double a i r e ( ) {
r e t u r n Double . PI ∗ t h i s . r a y o n ∗ t h i s . r a y o n ;
}
p u b l i c double a i r e ( ) {
return this . l a r g e u r ∗ this . longueur ;
}
}
}
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
98 / 121
Exemples du standard
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
99 / 121
Outline
Extrait de la documentation de java.lang.Number :
I
The abstract class Number is the superclass of classes
BigDecimal, BigInteger, Byte, Double, Float, Integer,
Long, and Short.
I
Subclasses of Number must provide methods to convert the
represented numeric value to byte, double, float, int,
long, and short.
L’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
Préambule et définition
Déclaration et implémentation
Polymorphisme d’interface
Classe ou interface ?
Composition d’interfaces
public abstract i n t i n t V a l u e ( ) ;
p u b l i c a b s t r a c t long l o n g V a l u e ( ) ;
public abstract f l o a t f l o a t V a l u e ( ) ;
...
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
100 / 121
Outline
J. Sopena (INRIA/UPMC)
101 / 121
Préambule
L’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
Préambule et définition
Déclaration et implémentation
Polymorphisme d’interface
Classe ou interface ?
Composition d’interfaces
Problèmes à résoudre :
I
assurer qu’un ensemble de classes offre un service minimum
commun.
I
faire du polymorphisme avec des objets dont les classes
n’appartiennent pas à la même hiérarchie d’héritage.
I
utilisation d’objets sans connaître leur type réel.
Solution :
I
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
Le polymorphisme en Java.
102 / 121
la définition d’un type complètement abstrait nommé
interface (notion de contrat).
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
103 / 121
Définition
Outline
Quand toutes les méthodes d’une classe sont abstraites et qu’il
n’y a aucun attribut, on aboutit à la notion d’interface.
Définition
I
Une interface est un prototype de classe. Elle définit la
signature des méthodes qui doivent être implémentées dans les
classes construites à partir de ce prototype.
I
Une interface est une “classe” purement abstraite dont toutes
les méthodes sont abstraites et publiques. Les mots-clés
abstract et public sont optionnels.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
104 / 121
Déclaration : syntaxe
L’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
Préambule et définition
Déclaration et implémentation
Polymorphisme d’interface
Classe ou interface ?
Composition d’interfaces
J. Sopena (INRIA/UPMC)
Comme les classes abstraites, les interfaces ne sont pas
instanciables :
p u b l i c i n t e r f a c e Comparable {
p u b l i c a b s t r a c t boolean p l u s G r a n d ( O b j e c t o ) ;
}
I
Une interface ne possède pas d’attribut instance.
I
Une interface n’a pas de constructeur.
Le but des interfaces est définir des API :
public interface Tracable {
void d e s s i n e T o i ( ) ;
void d e p l a c e T o i ( i n t x , i n t y ) ;
}
I
toutes leurs méthodes sont public. Elles ne définissent pas les
mécanismes internes
I
tout leurs attributs de classe sont des constante, c’est-à-dire
définir des attributs déclarées comme public static final et
ayant une valeur constante d’affectation. Exemple :
public abstract int f();
Remarque(s)
Dans les déclarations des méthodes de la classe Tracable, les mots
clés public et abstract sont implicites, mais ce n’est pas
recommandé.
Le polymorphisme en Java.
106 / 121
Implémentation d’une interface
public static final float PI = 3.14f;
J. Sopena (INRIA/UPMC)
107 / 121
Attention
On dit qu’une classe implémente une interface si elle définit
l’ensemble des méthodes abstraites de cette interface. On utilise
alors, dans l’entête de la classe, le mot-clé implements suivi du
nom de l’interface implémetée.
La classe doit implémenter toutes les méthodes de l’interface,
sinon elle doit être déclarée abstract.
class P e r s o n n e implements Comparable
{
p r i v a t e S t r i n g nom ;
p r i v a t e S t r i n g prenom ;
...
p u b l i c boolean p l u s G r a n d ( O b j e c t o ) {
r e t u r n t h i s . nom . compareTo ( ( ( P e r s o n n e ) o ) . nom ) | |
t h i s . prenom . compareTo ( ( ( P e r s o n n e ) o ) . prenom ) ;
}
}
Le polymorphisme en Java.
Le polymorphisme en Java.
Implémentation d’une interface
Définition
J. Sopena (INRIA/UPMC)
105 / 121
Déclaration : règles
La définition d’une interface se présente comme celle d’une classe,
en utilisant le mot-clé interface à la place de class.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
108 / 121
Outline
abstract class C e r c l e implements T r a c a b l e {
private i n t xCentre , yCentre ;
private i n t rayon ;
...
p u b l i c void d e p l a c e T o i ( i n t x , i n t y ) {
x C e n t r e += x ;
y C e n t r e += y ;
}
}
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
109 / 121
Utilisation comme type de données
L’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
Préambule et définition
Déclaration et implémentation
Polymorphisme d’interface
Classe ou interface ?
Composition d’interfaces
Une interface peut remplacer une classe pour déclarer :
I
un attribut
I
une variable
I
un paramètre
I
une valeur de retour
A l’exécution, la donnée correspond à une référence d’un objet dont
la classe implémente l’interface.
C’est suivant le type réel de cet objet que l’on choisira le code des
méthodes à exécuter.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
110 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
111 / 121
Exemple d’utilisation comme type de données.
Exemple de polymorphisme dans un tableau
p u b l i c class L i s t e E l e m e n t s {
Comparable [ ] t a b ;
i n t nbElements = 0 ;
...
p u b l i c class Main {
p u b l i c s t a t i c void main ( S t r i n g [ ] a r g s ) {
Comparable v a r 1 , v a r 2 ;
...
i f ( var1 . plusGrand ( var2 )) {
System . o u t . p r i n t l n ( " Var1 ␣ e s t ␣ p l u s ␣ g r a n d ␣ que ␣ v a r 2 " ) ;
} else {
System . o u t . p r i n t l n ( " Var1 ␣ e s t ␣ p l u s ␣ p e t i t ␣ que ␣ v a r 2 " ) ;
}
}
}
p u b l i c void a d d E l e m e n t ( Comparable e ) {
tab [ nbElements ] = e ;
n b E l e m e n t s++ ;
}
p u b l i c boolean c r o i s s a n t ( ) {
f o r ( i n t i = 1 ; i < n b E l e m e n t s ; i ++) {
i f ( tab [ i −1]. plusGrand ( tab [ i ] ) )
return false ;
}
return true ;
}
Ici les variables var1 et var2 contiennent des références vers des
objets dont les classes :
I
peuvent être différentes
I
implémentent l’interface Comparable
J. Sopena (INRIA/UPMC)
}
Le polymorphisme en Java.
112 / 121
Outline
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
113 / 121
Choix entre classe et interface : principe
Une interface peut servir à faire du polymorphisme comme
l’héritage, alors comment choisir entre classe et interface ?
L’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
Préambule et définition
Déclaration et implémentation
Polymorphisme d’interface
Classe ou interface ?
Composition d’interfaces
1. Choix dicté par l’existant : L’héritage n’est plus possible, la
classe hérite déjà d’une autre classe. Il ne reste plus que celui
l’interface.
2. Choix à la conception : On étudie la relation entre A et B ?
I
Un objet de classe B "EST UN" A
I
Un objet de classe B "EST CAPABLE DE FAIRE" A
=⇒ Héritage : B extends A.
=⇒ Interface : B implements A.
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
114 / 121
Choix entre classe et interface : exemple
J. Sopena (INRIA/UPMC)
extends Amphibien {
implements Amphibie {
Le polymorphisme en Java.
116 / 121
Implémentation de plusieurs interfaces
extends Batracien implements Amphibie
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
117 / 121
Extension d’une interface
Une classe peut hériter d’une autre classe et implémenter une
interface :
class G r e n o u i l l e
...
115 / 121
L’héritage
Polymorphisme et héritage
Classes et méthodes abstraites
Interfaces
Préambule et définition
Déclaration et implémentation
Polymorphisme d’interface
Classe ou interface ?
Composition d’interfaces
Une grenouille "EST CAPBLE DE FAIRE" amphibie :
class G r e n o u i l l e
...
}
Le polymorphisme en Java.
Outline
Une grenouille "EST UN" amphibien :
class G r e n o u i l l e
...
}
J. Sopena (INRIA/UPMC)
{
Lorsqu’une capacité s’exprime comme une extension d’une autre
capacité, on peut étendre une interface en utilisant le mot clé
extends :
}
interface SavoirConduire {
...
}
Une classe peut implémenter plusieurs interfaces :
class G r e n o u i l l e
...
}
J. Sopena (INRIA/UPMC)
implements SurTerre, SurEau
Le polymorphisme en Java.
i n t e r f a c e S a v o i r P i l o t e r extends S a v o i r C o n d u i r e
p u b l i c a b s t r a c t void d e r a p e r ( i n t d e g r e ) ;
}
{
118 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
{
119 / 121
Composition de plusieurs interfaces
Polymorphisme d’interfaces
Comme pour les classes, on peut faire du polymorphisme
d’interfaces.
Lorsqu’une capacité s’exprime comme un ensemble d’autres
capacités, on peut faire de la composition d’interfaces en utilisant
le mot clé extends :
i n t e r f a c e Amphibie extends S u r T e r r e , SurEau
...
p u b l i c c l a s s C h a u f f e u r extends Homme implements S a v o i r C o n d u i r e {
...
}
{
p u b l i c c l a s s P i l o t e extends Homme implements S a v o i r P i l o t e r {
...
}
}
public class Course {
p u b l i c s t a t i c void main ( S t r i n g [ ] a r g s ) {
SavoirConduire [10] participants ;
Attention
C h a u f f e u r j u l i e n = new C h a u f f e u r ( ) ;
P i l o t e s e b a s t i e n L o e b = new P i l o t e ( ) ;
Même si l’on utilise le même mot clé que pour l’héritage, ce n’est
pas de l’héritage multiple qui n’existe pas en Java.
participants [0] = julien ;
participants [1] = sebastienLoeb ;
}
}
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
120 / 121
J. Sopena (INRIA/UPMC)
Le polymorphisme en Java.
121 / 121
Téléchargement