• Aucun résultat trouvé

Le polymorphisme en Java support de cours de base

N/A
N/A
Protected

Academic year: 2021

Partager "Le polymorphisme en Java support de cours de base"

Copied!
118
0
0

Texte intégral

(1)

Cours JAVA :

Le polymorphisme en Java.

Version 3.01

Julien Sopena1

1[email protected]

Équipe REGAL - INRIA Rocquencourt LIP6 - Université Pierre et Marie Curie

(2)

Grandes lignes du cours

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 Principes du polymorphisme Protocoles et polymorphisme Les protocoles standards Downcasting : la fin du polymorphisme.

Le polymorphisme impose des limites à l’héritage Classes et méthodes abstraites

Principes des classes abstraites

Exemple de classe abstraite Interfaces Préambule et définition Déclaration et implémentation Polymorphisme d’interface Classe ou interface ? Composition d’interfaces

(3)

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

(4)

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

(5)

Rappel – principes de la POO

1. Encapsulation

I Rapprochement des données (attributs) et traitements

(méthodes)

I Protection de l’information (privateetpublic)

2. Agrégation (et composition)

I Classe A "A UN" Classe B

3. Utilisation

I Classe A "UTILISE" Classe B

A ... B ... A ... B ...

(6)

Un nouveau principe POO : Héritage

Définition

Le termehéritage désigne le principe selon lequel une classe peut hériter des caractéristiques (attributs et méthodes) d’autres classes.

Soient deux classes A et B

I Relation d’héritage : Classe B "EST UN" Classe A

I A est la super-classe ou classe mère de B

I B est la sous-classe ou classe fille de A

I Exercice : Héritage, Agrégation ou Utilisation ?

I Cercle et Ellipse ?

I Salle de bains et Baignoire ?

I Piano et Joueur de piano ?

I Entier et Réel ?

(7)

Motivation pour un nouveau type de relation

entre classes

Une classe décrit les services (comportements et données) d’un ensemble d’individus

Exemple : la classe Animal (animation graphique) Animal

+getNom(): String +manger(...): ... +dormir(...): ... +reproduire(...): ...

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( ), ...)

(8)

Les mauvaises solutions

1. Faire que la classe Animal puisse vraiment représenter tous les animaux

I accroître l’interface publique (tous les services possibles de

tous les animaux)

I ajouter des attributs booléens pour les catégories (isOiseau,

isPoisson, ...) ou un attribut qui indique la catégorie

I tester les attributs pour savoir si on peut répondre à un

message

I Exemple : Animal unChat = new Animal ("chat",...); (avec un

attribut genreAnimal de type String dans la classe Animal)

I code très complexe et non maintenable

2. Faire autant de classes qu’il existe d’espèces animales

I beaucoup de services vont être très similaires entre les classes I beaucoup de factorisations perdues

(9)

Classification hiérarchisée

Animal

Vertébré

Invertébré

Mammifère

Poisson

Reptile

Homme

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

(10)

Héritage

I Une sous-classe héritedes 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

Animal getNom() setNom() Vertébré remuerVertèbres() Invertébré Mammifère

allaiter() Poissonnager()

Homme

(11)

Hiérarchie en Java

I Une classe hérite toujours d’une seule et unique classe

(héritage simple versus héritage multiple)

I Cette classe est dite super-classede lasous-classe

I Par défaut, toute classe hérite de la classeObjectqui est la racine unique de l’arbre d’héritage

Object

Animal Question ...

Vertébré Invertébré

(12)

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

(13)

Syntaxe

Pour indiquer qu’une classe hérite d’une autre classe, on utilise le mot-cléextends.

p u b l i c c l a s s A p p a r t e m e n t extends Logement

Important

La classe Appartement ainsi définiepossèdetoutes les caractéris-tiques de la classe Logement (i.e., ses élémentsprivés et publics).

(14)

Spécialisation

p u b l i c c l a s s 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 ; p u b l i c 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 v e n d u ; } p u b l i c c l a s s A p p a r t e m e n t extends Logement { f i n a l p u b l i c i n t e t a g e ; p r i v a t e boolean c a v e ; }

Les attributs de la classe Appartement sont : surface, prix, proprietaire, vendu, etage et cave.

(15)

Implémentation en Java

p u b l i c c l a s s 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 { . . . } e l s e { . . . } } }

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 an ima ux ( h é r i t é ) unHomme . setNom ("Adam") ;

(16)

Héritage de comportements

Durant l’exécution, l’instruction : unHomme . setNom ("Adam") ;

provoque :

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

(17)

À retenir : la classe Object

Important

En Java, toutes les classes héritent de la classe Object.

La déclaration

p u b l i c c l a s s A { . . . } doit donc être comprise comme

p u b l i c c l a s s A extends O b j e c t { . . . } même si on ne l’écrit pas ainsi.

(18)

À retenir : le mot-clé

super

Á retenir

Java fournit la référence super qui désigne pour chaque classe, sa classe mère.

(19)

Héritage d’attributs

p u b l i c c l a s s A n i m a l {

// a t t r i b u t s p r o p r e s à t o u s l e s a ni ma ux 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 c l a s s 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 p r i v a t e i n t n b V e r t è b r e s ; . . . p u b l i c void s e t N b V e r t è b r e s (i n t n ) { n b V e r t è b r e s = 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 "

+ n b V e r t è b r e s + " v e r t è b r e s ") ; }

(20)

Héritage d’attributs – suite

p u b l i c c l a s s 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) ; t h i s. d r o i t i e r = d r o i t i e r ; } . . . }

(21)

Héritage d’attributs – fin

Homme uneFemme = new Homme("È v e ", t r u e) ;

Ève true uneFemme 50 true uneFemme . r e m u e r V e r t è b r e s ( ) ;

(22)

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

(23)

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é

p u b l i c c l a s s 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 ) { t h i s. s e t N b V e r t e b r e s ( 5 0 ) ; nom = unNom ; // e r r e u r t h i s. d r o i t i e r = d r o i t i e r ; } . . . }

(24)

Visibilité

Le modificateur qui précède chaque méthode (et attribut) détermine sa visibilité :

private défaut protected public

la classe elle-même OUI OUI OUI OUI

une sous-classe, paquetage = NON OUI OUI OUI

pas une sous-classe, paquetage = NON OUI OUI OUI

une sous-classe, paquetage 6= NON NON OUI OUI

pas une sous-classe, paquetage 6= NON NON NON OUI

Rappel

(25)

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

(26)

Instantiation des attributs hérités

p u b l i c c l a s s 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) ; t h i s. d r o i t i e r = d r o i t i e r ; } . . . } Problèmes

I Obligation d’introduire des modificateurs telles que Vertébré.setNbVertèbres()

I Redondance – la super-classe Mammifère doit avoir un constructeur

(27)

Héritage et construction – Correction

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.

p u b l i c c l a s s 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 ;

p u b l i c Homme ( S t r i n g unNom , boolean d r o i t i e r , i n t n b V e r t è b r e s ) { // 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 ) ; t h i s. d r o i t i e r = 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 ) { t h i s( unNom , d r o i t i e r , NB_VERTEBRES ) ;

} }

(28)

Règles d’utilisation d’un constructeur de la classe

mère.

Règles

1. L’appel d’un constructeur de la classe mère doit être la première instruction du constructeur de la classe fille. 2. Iln’est pas possibled’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 c l a s s A { p u b l i c A(i n t x ) {

super( ) ; t h i s( ) ; }

(29)

Constructeur implicite

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 c l a s s 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 t h i s. x = x ; . . . } }

Attention: Dans ce cas, le constructeur sans argument doit être défini dans la super-classe

(30)

Constructeur implicite : exemple

p u b l i c c l a s s 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 c l a s s B extends A {

p u b l i c B ( ) { System . o u t . p r i n t l n ("B") ; } } Le ligne de code suivante :

B c = new B ( ) ;

produira l’affichage suivant :

java MonProg A

(31)

Constructeur implicite : erreur fréquente

Etape 1 : Jusqu’ici tout va bien.

p u b l i c c l a s s A { p u b l i c i n t x ; } p u b l i c c l a s s B extends A { p u b l i c i n t y ; p u b l i c B (i n t x ,i n t y ) { t h i s. x = x ; t h i s. y = y ; } } Etape 2 :

Puis, on ajoute un constructeur.

p u b l i c c l a s s A { p u b l i c i n t x ; public A (int x) { this.x =x; } } p u b l i c c l a s s B extends A { p u b l i c i n t y ; p u b l i c B (i n t x ,i n t y ) { t h i s. x = x ; t h i s. y = y ; } }

(32)

Constructeur implicite : erreur fréquente

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 c l a s s B extends A { p u b l i c i n t y ; p u b l i c 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 t h i s. x = x ; t h i s. y = y ; } }

(33)

Constructeur implicite : Solutions

Solution 1 :

Ajout d’un constructeur vide.

p u b l i c c l a s s A { p u b l i c i n t x ; public A () {} p u b l i c A (i n t x ) { t h i s. x = x ; } } p u b l i c c l a s s B extends A { p u b l i c i n t y ; p u b l i c B (i n t x ,i n t y ) { t h i s. x = x ; t h i s. y = y ; } } Solution 2 :

Appel explicite au super(int).

p u b l i c c l a s s A { p u b l i c i n t x ; p u b l i c A (i n t x ) { t h i s. x = x ; } } p u b l i c c l a s s B extends A { p u b l i c i n t y ; p u b l i c B (i n t x ,i n t y ) { super(x); t h i s. y = y ; } }

(34)

Constructeur d’une classe dérivée

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.

Corollaire

Comme tout objet dérive (directement ou indirectement) de la

classe Object : Tout constructeur commence par exécuter

(35)

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

(36)

Définition de la redéfinition.

Définition

On appelleredé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éesans changer sa signature.

p u b l i c c l a s s A { p u b l i c i n t f (int x) { . . . } } p u b l i c c l a s s B e x t e n d A { p u b l i c i n t f (int x) { . . . } }

(37)

La signature d’une méthode Java

p u b l i c c l a s s 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 ") ; } } p u b l i c c l a s s 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 ") ; } }

(38)

Overloading vs Overriding

ATTENTION

Il ne faut pas confondre laredé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.

(39)

Surcharge d’une méthode redéfinie

On peutaussi surcharger une méthode redéfinie.

p u b l i c c l a s s 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 ) { t h i s. p r o p r i e t a i r e = a c q u e r e u r ; t h i s. v e n d u = t r u e; } } p u b l i c c l a s s A p p a r t e m e n t 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 ) { t h i s( a c q u e r e u r ) ; t h i s. c a v e = f a l s e: } 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 ) { t h i s( a c q u e r e u r ) ; t h i s. c a v e = c a v e : } }

(40)

Spécialiser une méthode héritée

La référencesuperpermet 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écialisela méthode héritée f.

p u b l i c c l a s s A { p u b l i c void f ( ) { . . . } } p u b l i c c l a s s B extends A { p u b l i c void f ( ) { . . . super.f() . . . } }

(41)

Spécialiser une méthode héritée : exemple

p u b l i c c l a s s P o i n t { p r i v a t e i n t x , y ; . . . p u b l i c S t r i n g t o S t r i n g ( ) { r e t u r n " ( " + x + " , " + y + " ) "; } } p u b l i c c l a s s 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 ; . . . p u b l i c 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 ( ) + " \ n C o u l e u r ␣ : ␣ " + t h i s. c o u l e u r ; } }

(42)

Limite pour désigner une méthode redéfinie

Attention

On ne peut remonterplus haut que la classe mèrepour récupérer une méthode redéfinie :

I pas de cast (ClasseAncetre)m()

(43)

Annotation pour la redéfinition

Depuis Java 5, on peut annoter par@Override les redéfinitions de méthodes. Ceci est très utile pourrepérer des fautes de frappedans 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 c l a s s P o i n t { p r i v a t e i n t x , y ; . . . @Override p u b l i c S t r i n g t o s t r i n g ( ) { r e t u r n " ( " + x + " , " + y + " ) "; } }

Point.java:3: method does not override or implement a method from a supertype

@Override ˆ

(44)

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

(45)

Les fondements de la covariance

Rappels

1. Laredéfinitiond’une méthode c’est le fait de donner une nouvelle implémentation en conservant la signature. 2. Lasignatured’une méthode est composée de son nom et

des types de ses arguments.

Définition

On appellecovariancele 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.

(46)

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

(47)

classes finales

Lors de la conception d’une classe, le concepteur peut empêcher que d’autres classes héritent d’elle (classe finale).

f i n a l p u b l i c c l a s s A { }

Remarque(s)

(48)

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éclarantfinal.

p u b l i c c l a s s A { f i n a l p u b l i c void f ( ) {} } p u b l i c c l a s s B extends A { // on ne p e u t p a s r e d é f i n i r f ( ) ! }

(49)

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 Classes et méthodes abstraites

(50)

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 Classes et méthodes abstraites

(51)

Polymorphisme : définition

Définition

Lepolymorphisme peut être vu comme la capacité de choisir dynamiquement la méthode qui correspond au type réel de l’objet.

(52)

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)

Lepolymorphismeconsiste à exploiter cela en fournissant un B dans les expressions "qui attendent" un A.

// un homme e s t un a n i m a l

A n i m a l anim1 = new Homme(" C a ï n ", f a l s e) ; // un c h a t a u s s i

A n i m a l 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 ;

(53)

Choix de la méthode : liaison dynamique

p u b l i c c l a s s P o i n t { p r i v a t e i n t x , y ; . . . p u b l i c S t r i n g t o S t r i n g ( ) { r e t u r n " ( " + x + " , " + y + " ) "; } } p u b l i c c l a s s 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 ; . . . p u b l i c 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 ( ) + " \ n C o u l e u r ␣ : ␣ " + t h i s. c o u l e u r ; } }

(54)

Choix de la méthode : liaison dynamique (suite)

p u b l i c c l a s s T r a c e u r D e L i g n e { 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 ␣ : ␣ " ) ; f o r ( P o i n t p : t a b ) System . o u t . p r i n t l n (" ␣−␣ " + p . toString ( ) ) ; } } }

(55)

Choix de la méthode : liaison dynamique (suite)

Si p référence une PointCouleur, quelle méthode toString() va être invoquée ?

1. La méthode toString() est définie dans Point 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

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.protectedpublic) mais elle ne peut pas être réduite (ex.public6→ private)

(56)

Écrire du code polymorphe : le problème

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.

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 ( . . . ) ;

Cage uneCage2 = new Cage ( . . . ) ; // 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 ) ; // 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 ) ; } }

(57)

Écrire du code polymorphe : la mauvaise solution

p u b l i c c l a s s 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 ) { . . . } }

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

(58)

Écrire du code polymorphe : la bonne solution

La bonne solution consiste à utiliser lepolymorphisme, en implémentant une méthode acceuillir générique pour tout les animaux.

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 c l a s s 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 ") ; . . . } }

(59)

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 Classes et méthodes abstraites

(60)

Motivation

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 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 ( . . . ) ;

Homme unHomme = new Homme ( . . . ) ;

uneCage . a c c u e i l l i r ( unHomme ) ; =⇒ il refuse !!! }

(61)

Première solution

p u b l i c c l a s s Cage { . . . p u b l i c void a c c u e i l l i r ( A n i m a l 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 ") ; r e t u r n; . . . } } Très mauvaise solution

I Des connaissances propres à la classe Homme sont dans la classe Cage

I si une nouvelle espèce animale refuse d’aller en cage, il faudra modifier le code de la classe Cage

(62)

Mise en place d’un protocole

p u b l i c c l a s s Cage { . . . p u b l i c void a c c u e i l l i r ( A n i m a l 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 ") ; r e t u r n; } . . . } }

I 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

(63)

Vue de l’arbre d’héritage

Animal supporteCage() ⇒ false Vertébré supporteCage() ⇒ true Invertébré

Mammifère PoissonsupporteCage() ⇒ false

Homme supporteCage()

(64)

Mise en place d’un protocole

p u b l i c c l a s s 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 f a l s e; } } 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; } }

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 v o i d 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 ( ) ;

} }

(65)

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 Classes et méthodes abstraites

(66)

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 v o i d 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 ( u n L i o n ) ; S i n g e u n S i n g e = new S i n g e ( . . . ) ; l e s C a g e s [ 1 ] . a c c u e i l l i r ( u n S i n g e ) ; f o r ( Cage c : l e s C a g e s ) { S y s t e m . o u t . println(c.contenu()) ; i f ( u n L i o n . equals(c.contenu()) S y s t e m . 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 ") ; } } }

I La classe Lion ne dispose pas de méthode equals(), pourquoi n’y a-t-il pas d’erreur de compilation ?

(67)

Le protocole toString()

p u b l i c c l a s s S y s t e m { p u b l i c s t a t i c P r i n t S t r e a m out ; . . . } p u b l i c c l a s s P r i n t S t r e a m { p u b l i c v o i d p r i n t ( Object a r g ) { p r i n t ( a r g . toString() ) ; } . . . } 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 ( ) ) ; } . . . }

(68)

Le protocole toString() – suite

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

p u b l i c c l a s s A n i m a l { . . . @ O v e r r i d e p u b l i c 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 ( ) ; } }

(69)

Le protocole equals()

La classe Object dispose d’une méthode equals()

p u b l i c c l a s s 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 ; } . . . }

Elle ne retournetrue que si les deux références désignent le même objet

(70)

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 :

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 ) 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 ( 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.

(71)

Spécialisation de equals() dans vos classes

p u b l i c c l a s s C o o r d o n n é e { p r i v a t e i n t 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 ) r e t u r n t r u e; i f ( o b j == n u l l) r e t u r n f a l s e; // 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 ( ) ) r e t u r n f a l s e; // 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 ) ; } }

(72)

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 Classes et méthodes abstraites

(73)

Upcasting : classe fille → classe mère

Définition

On appellesurclassement ou upcastingle 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.

p u b l i c c l a s s A { . . . }

p u b l i c c l a s s 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 ) .

On dit que a1 est une référencesurclassée(elle est du type A et contient l’adresse d’une instance d’une sous-classe de A).

(74)

Downcasting : classe mère → classe fille

Définition

On appelledéclassementou downcastingle 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 decast :

(<nomClasse>).

p u b l i c c l a s s A { . . . }

p u b l i c c l a s s B extends A { . . . }

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

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 !

(75)

Downcasting : mise en garde !

Attention

Le downcasting ne permet pas de convertir une instance d’une classe donnée en une instance d’une sous-classe !

c l a s s A { A ( ) {}}

c l a s s B extends A { B ( ) {}} A a = new A ( ) ;

B b = (B) a ;

Ça compile, mais ça plantera à l’exécution :

Exception in thread "main" java.lang.ClassCastException: A cannot be cast to B

(76)

Downcasting : utilisation de

instanceof

On peut utiliser le mot-cléinstanceofpour savoir si une référence d’une classe donnée ou d’une de ces sous-classes.

Si a est une référence de type B alors l’expression ainstanceofA renvoietruesi B est une sous-classe de A etfalse 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 . ") ; }

Remarque(s)

Attention, l’utilisation d’instanceofest souvent la marque d’un défaut de conception et va à l’encontre du polymorphisme.

(77)

Exemple : classe rendant un service générique.

p u b l i c c l a s s G a r a g e { V e h i c u l e [ ] t a b ; i n t n b V e h i c u l e s ; G a r a g e (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 ] ; n b V e h i c u l e s = 0 ; } v o i d 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 ; } V e h i c u l e s o r t i r V e h i c u l e ( ) { 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 ] ; e l s e r e t u r n n u l l; } }

(78)

Exemple : polymorphisme d’héritage

p u b l i c c l a s s V e h i c u l e { . . . } p u b l i c c l a s s Moto extends V e h i c u l e { . . . } p u b l i c c l a s s V o i t u r e extends V e h i c u l e { i n t t e m p e r a t u r e ; . . . 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 ; } }

(79)

Exemple : le downcast c’est la fin du

polymorphisme

p u b l i c c l a s s 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 r a 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 ( ( V o i t u r e ) u n V e h i c u l e ) . a u g m e n t e r C h a u f f a g e ( 1 0 ) ; } } }

(80)

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

Classes et méthodes abstraites Interfaces

(81)

Ce qu’on ne peut pas faire et ne pas faire

Pour permettre le polymorphisme :

=⇒ une sous classe doit pouvoir se faire passer pour une sur classeur ;

=⇒ 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).

Par contre on peut toujours ajouter/modifier des choses : I On peut ajouter des membres ;

I On peut redéfinir des méthodes ;

(82)

Problème de la covariance

Dans cet exemple decovariance, peut-on choisir Y librement ?

p u b l i c c l a s s A { . . . p u b l i c X f (i n t x ) { . . . } } p u b l i c c l a s s B extends A { . . . @ O v e r r i d e p u b l i c Y f (i n t x ) { . . . } }

(83)

Problème de la covariance

Dans cet exemple decovariance, peut-on choisir Y librement ?

p u b l i c c l a s s A { . . . p u b l i c X f (i n t x ) { . . . } } p u b l i c c l a s s B extends A { . . . @ O v e r r i d e p u b l i c Y f (i n t x ) { . . . } }

(84)

Limite de la covariance

p u b l i c c l a s s 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 ) ; } }

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

(85)

Limite de la covariance

Règle de covariance

Lorsque l’on fait de la redéfinition avec covariance, le nouveau type de retour doit toujours être un sous-typedu type de retour original.

(86)

Outline

L’héritage

Polymorphisme et héritage

Classes et méthodes abstraites

Principes des classes abstraites Exemple de classe abstraite Interfaces

(87)

Outline

L’héritage

Polymorphisme et héritage

Classes et méthodes abstraites Principes des classes abstraites Exemple de classe abstraite Interfaces

(88)

Motivation

p u b l i c c l a s s 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 ( A n i m a l a , N o u r r i t u r e n ) { . . . a . manger ( n ) ; . . . } . . . }

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 ?

(89)

Spécification d’un protocole sans implémentation

par défaut

Spécification du protocole– le plus haut possible dans l’arbre d’héritage

p u b l i c abstract c l a s s A n i m a l { . . .

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 é

. . . }

Spécialisation du protocole– là où c’est nécessaire dans l’arbre d’héritage

p u b l i c c l a s s 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 } . . . }

(90)

Méthodes abstraites =⇒ Classe abstraite

Définition

Un classe contenantau moinsune méthode abstraite est appelée uneclasse abstraiteet cela doit être explicitement précisé dans la déclaration avec :abstract class

Remarque(s)

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.

(91)

Classe abstraite : instanciation et spécialisation.

I Une classe abstraite constitue un type à part entière :

A n i m a l u n A n i m a l ; // OK

I Une classe abstraite ne peut pas être instanciée, en effet son comportement n’est pas complètement défini :

A n i m a l u n A n i m a l = new A n i m a l ( . . . ) ; // ERREUR

I Une sous-classe d’une classe abstraite peut

I 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.

(92)

Outline

L’héritage

Polymorphisme et héritage

Classes et méthodes abstraites

Principes des classes abstraites Exemple de classe abstraite

(93)

Exemple : besoin

Considérons la hiérarchie de classes suivantes :

Figure

aire()

Cercle

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.

(94)

Exemple : déclaration de la classe abstraite.

p u b l i c a b s t r a c t c l a s s F i g u r e { p r i v a t e S t r i n g nom ; // 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 ; } // 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 ( ) ; // T o u t e s l e s m é t h o d e s ne s o n t p a s a b s t r a i t e s : p u b l i c 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 (" J e ␣ s u i s ␣ un ␣ " + t h i s. nom ) ; } }

(95)

Exemple : première implémentation.

p u b l i c c l a s s 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 ") ; t h i s. r a y o n = r a y o n ; } p u b l i c double a i r e ( ) { r e t u r n D o u b l e . P I ∗ t h i s. r a y o n ∗ t h i s. r a y o n ; } }

(96)

Exemple : deuxième implémentation.

p u b l i c c l a s s 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 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 ") ; t h i s. l a r g e u r = l a r g e u r ; t h i s. l o n g u e u r = l o n g u e u r ; } p u b l i c double a i r e ( ) { r e t u r n t h i s. l a r g e u r ∗ t h i s. l o n g u e u r ; } }

(97)

Exemples du standard

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.

p u b l i c a b s t r a c t 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 ( ) ; p u b l i c a b s t r a c t f l o a t f l o a t V a l u e ( ) ;

(98)

Outline

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

(99)

Outline

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

(100)

Préambule

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 la définition d’un type complètement abstrait nommé

(101)

Définition

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 Uneinterfaceest 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 Uneinterfaceest une “classe” purement abstraite dont toutes les méthodes sont abstraites et publiques. Les mots-clés abstractet public sont optionnels.

(102)

Outline

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

(103)

Déclaration : syntaxe

La définition d’une interface se présente comme celle d’une classe, en utilisant le mot-cléinterface à la place declass.

p u b l i c i n t e r f a c e C o m p a r a b l e { 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 ) ; } p u b l i c i n t e r f a c e T r a c a b l e { 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 ) ; } Remarque(s)

Dans les déclarations des méthodes de la classe Tracable, les mots cléspublic etabstractsont implicites, mais ce n’est pas

(104)

Déclaration : règles

Comme les classes abstraites, les interfaces ne sont pas instanciables :

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 :

I toutes leurs méthodes sont public. Elles ne définissent pas les mécanismes internes

public abstract int f();

I tout leurs attributs de classe sont des constante, c’est-à-dire définir des attributs déclarées commepublic static finalet ayant une valeur constante d’affectation. Exemple :

(105)

Implémentation d’une interface

Définition

On dit qu’une classeimplémenteune 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.

c l a s s 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 ) ; }

(106)

Implémentation d’une interface

Attention

La classe doit implémenter toutes les méthodes de l’interface, sinon elle doit être déclaréeabstract.

abstract c l a s s C e r c l e implements T r a c a b l e { p r i v a t e i n t x C e n t r e , y C e n t r e ; p r i v a t e i n t r a y o n ; . . . 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 ; } }

(107)

Outline

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

(108)

Utilisation comme type de données

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.

(109)

Exemple d’utilisation comme type de données.

p u b l i c c l a s s 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 ) { C o m p a r a b l e v a r 1 , v a r 2 ; . . . i f ( v a r 1 . p l u s G r a n d ( v a r 2 ) ) {

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 ") ; } e l s e {

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 ") ; }

} }

Ici les variables var1 et var2 contiennent des références vers des objets dont les classes :

I peuvent être différentes

(110)

Exemple de polymorphisme dans un tableau

p u b l i c c l a s s L i s t e E l e m e n t s { C o m p a r a b l e [ ] t a b ; i n t n b E l e m e n t s = 0 ; . . . p u b l i c void a d d E l e m e n t ( C o m p a r a b l e e ) { t a b [ n b E l e m e n t s ] = 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 ( t a b [ i − 1 ] . p l u s G r a n d ( t a b [ i ] ) ) r e t u r n f a l s e; } r e t u r n t r u e; } }

(111)

Outline

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

(112)

Choix entre classe et interface : principe

Une interface peut servir à faire du polymorphisme comme l’héritage, alors comment choisir entre classe et interface ?

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

=⇒ Héritage: BextendsA.

I Un objet de classe B"EST CAPABLE DE FAIRE"A

(113)

Choix entre classe et interface : exemple

Une grenouille"EST UN"amphibien :

c l a s s G r e n o u i l l e extends A m p h i b i e n { . . .

}

Une grenouille"EST CAPBLE DE FAIRE"amphibie :

c l a s s G r e n o u i l l e implements A m p h i b i e { . . .

(114)

Outline

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

(115)

Implémentation de plusieurs interfaces

Une classe peut hériter d’une autre classe et implémenter une interface :

c l a s s G r e n o u i l l e extends Batracien implements A m p h i b i e { . . .

}

Une classe peut implémenter plusieurs interfaces :

c l a s s G r e n o u i l l e implements SurTerre, SurEau { . . .

(116)

Extension d’une interface

Lorsqu’une capacité s’exprime comme une extension d’une autre capacité, on peut étendre une interface en utilisant le mot clé

extends: i n t e r f a c e S a v o i r C o n d u i r e { . . . } 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 ) ; }

(117)

Composition de plusieurs 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 A m p h i b i e extends S u r T e r r e , SurEau { . . .

}

Attention

Même si l’on utilise le même mot clé que pour l’héritage,ce n’est pas de l’héritage multiplequi n’existe pas en Java.

(118)

Polymorphisme d’interfaces

Comme pour les classes, on peut faire dupolymorphisme d’interfaces.

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 { . . . } p u b l i c c l a s s C o u r s e { 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 ) { S a v o i r C o n d u i r e [ 1 0 ] p a r t i c i p a n t s ; 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 ( ) ; p a r t i c i p a n t s [ 0 ] = j u l i e n ; p a r t i c i p a n t s [ 1 ] = s e b a s t i e n L o e b ; } }

Références

Documents relatifs

Héritage simple : classe dérivée n’a qu’une seule classe de base Héritage multiple : classe dérivée a plus d’une classe de base.

Exemple: Dans une table ETUDIANT, la clé primaire peut être le champ.. «

public class Voiture extends Vehicule { private Roue[] roue = new

public class NomComplet extends Nom { private String prenom;// nouvelle var.

Si héritage il y a, en définitive, c’est peut-être tout simplement dans la coexistence de structures éditoria- les de masse, à la production calibrée et à la diffusion

• const C::`vftable' qui fournit l'implémentation de la fonction redéfinie GetInt() de la classe A et utilise la fonction de base SetInt() de la classe A,.. • const C1::`vftable'

Dans l’arrière-pays australien où il n’a pas plu depuis des mois, Maia et Xanthe Blake, 27 ans, les deux plus jeunes sœurs de Cassandra, abordent un tournant de leur

6- Ecrire la méthode void avancerAvecConflit(int n, Pion pio), qui fait la même chose que la méthodes avancer de la classe Pion et qui prend compte de cette modification (la