2I002
HÉRITAGE
SURCHARGE / REDÉFINITIONS
Vincent Guigue & Christophe Marsala
Surcharge Définition
Même nom de fonction / arguments différents
1 p u b l i c c l a s s P o i n t {
2 . . .
3 p u b l i c v o i d move (d o u b l e dx , d o u b l e dy ) {
4 x+=dx ; y+=dy ;
5 }
6 p u b l i c v o i d move (d o u b l e dx , d o u b l e dy , d o u b l e s c a l e ) {
7 x+=dx∗s c a l e ; y+=dy∗s c a l e ;
8 }
9 p u b l i c v o i d move (i n t dx , i n t dy ) {
10 x+=dx ; y+=dy ;
11 }
12 p u b l i c v o i d move ( P o i n t p ) {
13 x+=p . x ; y+=p . y ;
14 }
Rappel: dans la classe Point, vous avez accès aux attributs privés des autres instances de
Point
Surcharge: qui fait quoi
Le compilateur (pré)-sélectionne les méthodes:
Ces méthodes sont totalement différentes
(pour le compilateur qui analyse le type des arguments) Elles peuvent être indifféremment dans la classe ou la super-classe (mère)
1 p u b l i c c l a s s P o i n t {
2 . . .
3 p u b l i c v o i d move (d o u b l e dx , d o u b l e dy ) { // 1
4 x+=dx ; y+=dy ;
5 }
6 p u b l i c v o i d move (d o u b l e dx , d o u b l e dy , d o u b l e s c a l e ) { // 2
7 x+=dx∗s c a l e ; y+=dy∗s c a l e ;
8 }
9 . . .
10 // / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
11
12 P o i n t p = new P o i n t ( 1 , 2 ) ;
13 p . move ( 3 , 1 ) ; // p r e s e l e c t i o n de 1
14 p . move ( 3 , 1 , 0 . 5 ) ; // p r e s e l e c t i o n de 2
3/16
Surcharge: les limites
Pas de prise en compte du type de retour Interdiction d’avoir des signatures identiques
1 p u b l i c v o i d move (d o u b l e dx , d o u b l e dy ) {
2 x+=dx ; y+=dy ;
3 }
4
5 // Meme s i g n a t u r e p o u r l e c o m p i l a t e u r
6 // −> ERREUR de compilation
7 p u b l i c v o i d move (d o u b l e a , d o u b l e b ) {
8 x+=a ; y+=b ;
9 }
10
11 // Meme s i g n a t u r e p o u r l e c o m p i l a t e u r
12 // −> ERREUR de compilation
13 p u b l i c P o i n t move (d o u b l e dx , d o u b l e dy ) {
14 x+=dx ; y+=dy ;
15 r e t u r n t h i s;
16 }
Redéfinition:
Définition
Redéfinition d’une méthode de même signature dans la classe fille
1 p u b l i c c l a s s P o i n t {
2 . . .
3 p u b l i c v o i d a f f i c h e r ( ) { S y s t e m . o u t . p r i n t l n (" J e ␣ s u i s ␣ un ␣ P o i n t ") ; } // 1
4 }
5 //========================================
6 p u b l i c c l a s s PointNomme e x t e n d s P o i n t {
7 . . .
8 p u b l i c v o i d a f f i c h e r ( ) { S y s t e m . o u t . p r i n t l n (" J e ␣ s u i s ␣ un ␣ PointNomme ") ; }// 2
9 }
RAS à la compilation:
1 P o i n t p = new P o i n t ( 1 , 3 ) ;
2 PointNomme pn = new PointNomme ( 1 , 2 , " t o t o ") ;
3 P o i n t p2 = new PointNomme ( 1 , 3 , " t i t i ") ;
4 p . a f f i c h e r ( ) ;
5 pn . a f f i c h e r ( ) ;
6 p2 . a f f i c h e r ( ) ;
A l’exécution, la JVM décide de la méthode à invoquer en fonction du type de l’instance appelante
5/16
Exemples de fonctionnement - Cas 1/3 (facile)
1 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 ) {
2 P o i n t p = new P o i n t ( 1 , 2 ) ;
3 p . a f f i c h e r ( ) ;
4 }
Dans la classe Point, une seule méthode correspond à la signature afficher()
Affichage de :
1 J e s u i s un P o i n t
Exemples de fonctionnement - Cas 2/3 (résolution d’une ambiguité)
1 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 ) {
2 PointNomme p = new PointNomme ( 1 , 2 ," t o t o ") ;
3 p . a f f i c h e r ( ) ;
4 }
Dans la classe PointNomme, deux méthodes correspondent à la signature afficher() (méthodes accessibles: dans la classe et dans les classes parentes)
Une dans Point Une dans PointNomme
La JVM choisit, au moment de l’exécution du programme en fonction du type de l’instance de p, la méthode la plus proche
7/16
Exemples de fonctionnement - Cas 2/3 (résolution d’une ambiguité)
1 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 ) {
2 PointNomme p = new PointNomme ( 1 , 2 ," t o t o ") ;
3 p . a f f i c h e r ( ) ;
4 }
Affichage de :
Je suis un PointNomme
Exemples de fonctionnement - Cas 3/3 Surcharge + subsomption
1 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 ) {
2 P o i n t p = new PointNomme ( 1 , 2 ," t o t o ") ; // s u b s o m p t i o n
3 p . a f f i c h e r ( ) ; // ? ? ?
4 }
Compilation: (javac) = type des variables uniquement p = Point
void afficher() existe dans Point ⇒ OK
Execution: JVM regarde le type de l’instance référencée par p
p référence un PointNomme
recherche de void afficher() dans PointNomme
8/16
Exemples de fonctionnement - Cas 3/3 Surcharge + subsomption
1 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 ) {
2 P o i n t p = new PointNomme ( 1 , 2 ," t o t o ") ; // s u b s o m p t i o n
3 p . a f f i c h e r ( ) ; // ? ? ?
4 }
Affichage de :
Je suis un PointNomme
Usage de super 1/3
Le mot clé super permet:
de préciser que l’on va chercher des informations dans la super-classe (dans ce cas, super est optionnel)
1 p u b l i c c l a s s PointNomme e x t e n d s P o i n t {
2 p u b l i c v o i d a f f i c h e r ( ) {
3 S y s t e m . o u t . p r i n t l n (" J e ␣ s u i s ␣ un ␣ PointNomme ␣ " +
4 " de ␣ c o o r d o n n e e s ␣ : ␣ "+ s u p e r. g e t X ()+ " ␣ " + s u p e r. g e t Y ( ) ) ;
5 }
6 }
de forcer le programme à aller chercher une méthode dans la super-classe (obligatoire)
1 p u b l i c c l a s s PointNomme e x t e n d s P o i n t {
2 . . .
3 p u b l i c v o i d a f f i c h a g e G l o b a l ( ) {
4 a f f i c h e r ( ) ; // −> J e s u i s un PointNomme
5 t h i s. a f f i c h e r ( ) ; // −> J e s u i s un PointNomme
6 s u p e r. a f f i c h e r ( ) ; // −> J e s u i s un P o i n t
7 }
8 }
9/16
Usage de super 2/3
L’un des usages les plus classique concerne toString():
1 // c l a s s e P o i n t
2 p u b l i c S t r i n g t o S t r i n g ( ) {
3 r e t u r n " ( "+x+" , "+y+" ) ";
4 }
5
6 // c l a s s e PointNomme
7 p u b l i c S t r i n g t o S t r i n g ( ) {
8 r e t u r n " PointNomme ␣ [ name=" + name + s u p e r. t o S t r i n g ( ) + " ] ";
9 }
1
Quels sont les affichages en sortie du code suivant:
1 P o i n t p = new P o i n t ( 1 , 2 ) ;
2 PointNomme pn = new PointNomme ( 3 , 4 ," t o t o ") ;
3
4 S y s t e m . o u t . p r i n t l n ( p . t o S t r i n g ( ) ) ;
5 S y s t e m . o u t . p r i n t l n ( pn . t o S t r i n g ( ) ) ; 2
Que se passerait-il si on oublie le super?
Usage de super 3/3
Ajout d’une classe pour un Point lié à d’autres dans l’espace (système de graphe)
1 // d a n s PointNommeLie
2
3 t o S t r i n g ( ) ; // OK l o c a l
4 s u p e r. t o S t r i n g ( ) ; // OK s u p e r−c l a s s e
5 super.super.toString(); // s y n t a x e i n t e r d i t e
6
7 g e t X ( ) ; // OK, e x i s t e i c i p a r
8 // h e r i t a g e de P o i n t
9 s u p e r. g e t X ( ) ; // OK e x i s t e d a n s PointNomme
10 // p a r h e r i t a g e de P o i n t
Les méthodes redéfinies dans la super-classes empêchent l’accès aux versions de la génération supérieure.
11/16
Classe Object Classe standard
Toutes les classes dérivent de la classe Object de JAVA
12/16
Méthodes standards
Dans le cadre de l’UE, nous nous intéresserons à certaines méthodes dites standards String toString()
boolean equals(Object) Sur la classe basique suivante:
1 p u b l i c c l a s s P o i n t {
2 p r i v a t e d o u b l e x , y ;
3 p u b l i c P o i n t ( ) {
4 x =0; y =0;
5 }
6 }
Les opérations suivantes sont possibles:
1 P o i n t p1 = new P o i n t ( 1 , 2 ) ; P o i n t p2 = new P o i n t ( 1 , 2 ) ;
2 S y s t e m . o u t . p r i n t l n ( p1 . t o S t r i n g ( ) ) ;
3 S y s t e m . o u t . p r i n t l n ( p1 . e q u a l s ( p2 ) ) ;
4 S y s t e m . o u t . p r i n t l n ( p1 . e q u a l s ( p1 ) ) ;
Quelles sont les sorties associées?
13/16
Rappels sur boolean equals(Object o)
Par défaut, equals existe mais teste l’égalité référentielle, ce qui n’est pas intéressant...
Redéfinition = faire en sorte de tester les attributs Un processus en plusieurs étapes:
1
Vérifier s’il y a égalité référentielle:
sitruerenvoyertrue
2
Vérifier le type de l’Object o (cf prochain cours)
3
Convertir l’Object o dans le type de la classe (idem)
4
Vérifier l’égalité entre attributs
1 p u b l i c b o o l e a n e q u a l s ( O b j e c t o b j ) {
2 i f (t h i s == o b j ) r e t u r n t r u e;
3 i f ( o b j == n u l l) r e t u r n f a l s e;
4 i f ( g e t C l a s s ( ) != o b j . g e t C l a s s ( ) ) r e t u r n f a l s e;
5 P o i n t o t h e r = ( P o i n t ) o b j ;
6 i f ( x != o t h e r . x ) r e t u r n f a l s e;
7 i f ( y != o t h e r . y ) r e t u r n f a l s e;
8 r e t u r n t r u e;
9 }
Redéfinition et co-variance du résultat [E. Chailloux]
Depuis la version 1.5, il est possible dans le cadre d’une redéfinition de préciser le type de retour. Le type du résultat de la méthode redéfinie est en relation de sous-typage avec celui définie dans la sur-classe. On parle de co-variance du type résultat.
Exemple:
dans Object
1 p r o t e c t e d O b j e c t c l o n e ( ) { . . . }
dans Point
1 // p o u r e v i t e r l e s c a s t
2 p r o t e c t e d Point c l o n e ( ) {r e t u r n new P o i n t ( . . . ) ; }
dans PointNomme
1 p r o t e c t e d PointNomme c l o n e ( ) {r e t u r n new PointNomme ( . . . ) ; }
15/16
Ouverture de la redéfinition Définition
Il est possible d’augmenter la visibilité d’une méthode dans la classe fille mais pas de la réduire
Exemple:
dans Object
1 p r o t e c t e d O b j e c t c l o n e ( ) { . . . }
dans Point
1 // p o u r e v i t e r l e s c a s t
2 p r o t e c t e d P o i n t c l o n e ( ) {r e t u r n new P o i n t ( . . . ) ; }
dans PointNomme
1 // o u v e r t u r e de l a r e d e f i n i t i o n
2 public PointNomme c l o n e ( ) {r e t u r n new PointNomme ( . . . ) ; }
3 // p r i v a t e PointNomme c l o n e ( ) { r e t u r n new PointNomme ( . . . ) ; }
4 // Ne c o m p i l e p a s