• Aucun résultat trouvé

LU2IN002 CONVERSION DES TYPES DE VARIABLE (CAST...) TESTS DYNAMIQUES (INSTANCEOF)

N/A
N/A
Protected

Academic year: 2022

Partager "LU2IN002 CONVERSION DES TYPES DE VARIABLE (CAST...) TESTS DYNAMIQUES (INSTANCEOF)"

Copied!
22
0
0

Texte intégral

(1)

LU2IN002

CONVERSION DES TYPES DE VARIABLE (CAST...)

TESTS DYNAMIQUES (INSTANCEOF)

Vincent Guigue & Christophe Marsala

(2)

Exemple du logiciel de dessin

(3)

Récupérer le type d’une instance dynamiquement

Cas amusant:

le type des instances est parfois (souvent) inconnu

Exemple:

1 F i g u r e f ;

2 i f( Math . random ( ) > 0 . 5 )

3 f = new P o i n t ( 2 , 3 ) ;

4 e l s e

5 f = new Segment (new P o i n t ( 1 , 2 ) , new P o i n t ( 5 , 3 ) ) ;

6

7 // p o u r l e compilateur f e s t de t y p e F i g u r e

8 // p o u r l a JVM, q u e l e s t l e t y p e de l ’ i n s t a n c e f ? ? ?

(4)

Récupérer le type d’une instance dynamiquement

Les limites du polymorphisme sont imposées par le compilateur qui vérifie (statiquement) le type des variables

1) Contournement = connaitre le type des instances en cours de programme (dynamiquement)

2) Revenir au type de l’instance pour accéder aux méthodes spécifiques = faire un cast sur la variable

Exemple:

1 F i g u r e f ;

2 i f( Math . random ( ) > 0 . 5 )

3 f = new P o i n t ( 2 , 3 ) ;

4 e l s e

5 f = new Segment (new P o i n t ( 1 , 2 ) , new P o i n t ( 5 , 3 ) ) ;

6

7 // p o u r l e compilateur f e s t de t y p e F i g u r e

8 // p o u r l a JVM, q u e l e s t l e t y p e de l ’ i n s t a n c e f ? ? ?

(5)

1) récupération des informations : instanceof variable instanceof NomClasse

⇒ retourne un boolean

1 F i g u r e f ;

2 i f( Math . random ( ) > 0 . 5 )

3 f = new P o i n t ( 2 , 3 ) ;

4 e l s e

5 f = new Segment (new P o i n t ( 1 , 2 ) , new P o i n t ( 5 , 3 ) ) ;

6

7 i f( f i n s t a n c e o f P o i n t )

8 S y s t e m . o u t . p r i n t l n ("C ’ e s t ␣ un ␣ P o i n t ") ;

9 e l s e

10 S y s t e m . o u t . p r i n t l n ("C ’ e s t ␣ un ␣ Segment ") ;

Syntaxe particulière

Souvent, il existe d’autre moyen de faire...

Globalement, sauf exception:

instanceof = mauvaise programmation

(6)

instanceof : discussion

Procédure qui spécialise ses traitements par type de figure

1 p u b l i c s t a t i c v o i d a f f i c h e T y p e ( F i g u r e f ) {

2 i f( f i n s t a n c e o f P o i n t )

3 S y s t e m . o u t . p r i n t l n ("C ’ e s t ␣ un ␣ P o i n t ") ;

4 e l s e i f( f i n s t a n c e o f Segment )

5 S y s t e m . o u t . p r i n t l n ("C ’ e s t ␣ un ␣ P o i n t ") ;

6 e l s e i f( f i n s t a n c e o f R e c t a n g l e )

7 S y s t e m . o u t . p r i n t l n ("C ’ e s t ␣ un ␣ R e c t a n g l e ") ;

8 // e t c . . . un c a s p a r f i g u r e !

⇒ Très mauvais... Mais pourquoi ?

Que se passe-t-il si on ajoute un nouveau type de Figure ? Il faut toucher au code utilisateur !!!

⇒ l’outil existe, mais souvent, il faut mieux ne pas l’utiliser!

(7)

instanceof : discussion

Procédure qui spécialise ses traitements par type de figure

1 p u b l i c s t a t i c v o i d a f f i c h e T y p e ( F i g u r e f ) {

2 i f( f i n s t a n c e o f P o i n t )

3 S y s t e m . o u t . p r i n t l n ("C ’ e s t ␣ un ␣ P o i n t ") ;

4 e l s e i f( f i n s t a n c e o f Segment )

5 S y s t e m . o u t . p r i n t l n ("C ’ e s t ␣ un ␣ P o i n t ") ;

6 e l s e i f( f i n s t a n c e o f R e c t a n g l e )

7 S y s t e m . o u t . p r i n t l n ("C ’ e s t ␣ un ␣ R e c t a n g l e ") ;

8 // e t c . . . un c a s p a r f i g u r e !

⇒ Très mauvais... Mais pourquoi ?

Que se passe-t-il si on ajoute un nouveau type de Figure ? Il faut toucher au code utilisateur !!!

⇒ l’outil existe, mais souvent, il faut mieux ne pas l’utiliser!

(8)

instanceof: Solution

Code spécifique dans les classes:

dans Figure :

1 p u b l i c S t r i n g g e t T y p e F i g u r e ( ) { } ;

dans Point :

1 p u b l i c S t r i n g g e t T y p e F i g u r e ( ) { r e t u r n " P o i n t "; }

dans Rectangle :

1 p u b l i c S t r i n g g e t T y p e F i g u r e ( ) { r e t u r n " R e c t a n g l e "; }

Code générique (éventuellement en dehors des classes):

1 p u b l i c s t a t i c v o i d a f f i c h e T y p e ( F i g u r e f ) {

2 S y s t e m . o u t . p r i n t l n ("C ’ e s t ␣ un ␣ "+f . g e t T y p e F i g u r e ( ) ) ;

3 }

(9)

instanceof: attention à la hierarchie

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 p1 = new P o i n t (" t o t o ", 0 , 2 ) ;

3 P o i n t p2 = new P o i n t ( " t o t o ␣ 2 ", 3 , 2 ) ;

4 F i g u r e f = new Segment ( p1 , p2 ) ;

5

6 i f( f i n s t a n c e o f P o i n t )

7 S y s t e m . o u t . p r i n t l n (" f ␣ e s t ␣ un ␣ P o i n t ") ;

8 i f( f i n s t a n c e o f Segment )

9 S y s t e m . o u t . p r i n t l n (" f ␣ e s t ␣ un ␣ Segment ") ;

10 i f( f i n s t a n c e o f F i g u r e )

11 S y s t e m . o u t . p r i n t l n (" f ␣ e s t ␣ une ␣ F i g u r e ") ;

12 }

Le programme suivant retourne:

1 f e s t un Segment

2 f e s t une F i g u r e

Le résultat est logique: il faut comprendre instanceof comme «EST UN?»

(10)

Alternative à instanceof: getClass() public Class getClass()

Méthode de Object

S’utilise sur une instance (syntaxe différente de instanceof) Retourne la classe (complète) de l’instance

Unique pour une classe donnée

Accès à différents descripteurs de la classe

1 F i g u r e f = new Segment ( p1 , p2 ) ;

2 S y s t e m . o u t . p r i n t l n (" f ␣ e s t ␣ de ␣ t y p e ␣ : ␣ "+f . g e t C l a s s ( ) ) ;

3 // r e t o u r :

4 // f e s t de t y p e : c l a s s c o u r s 2 . Segment

Usage classique pour comparer le type de deux instances:

1 // s o i t d e u x O b j e t s o b j 1 e t o b j 2

2 i f ( o b j 1 . g e t C l a s s ( ) != o b j 2 . g e t C l a s s ( ) )

3 . . .

(11)

2) modifier le type d’une variable : Cast Cast = 2 modes de fonctionnement

Conversion sur les types basiques: le codage des données change. Souvent implicite dans votre codage...

1 d o u b l e d = 1 . 4 ;

2 i n t i = (i n t) d ; // i =1

Conversion dans les hiérarchies de classes:

la variable est modifiée, l’instance est inchangée

1 F i g u r e f = new Segment ( p1 , p2 ) ;

2 Segment s = ( Segment ) f ;

3 // Pour v e r i f i e r que v o u s a v e z c o m p r i s :

4 // d o n n e r un diagramme memoire

Utile pour accéder aux méthodes spécifiques d’une instance

Dangereux: aucun contrôle du compilateur...

(12)

Cast: limite

Un système peu sécurisé à la compilation:

1 P o i n t p1 = new P o i n t (" t o t o ", 0 , 2 ) ;

2 P o i n t p2 = new P o i n t ( " t o t o ␣ 2 ", 3 , 2 ) ;

3 F i g u r e f = new Segment ( p1 , p2 ) ;

4

5 F i g u r e f 2 = ( F i g u r e ) p1 ;

// OK m a i s i n u t i l e

6 F i g u r e f 3 = p1 ; // OK S u b s o m p t i o n c l a s s i q u e

7 Segment s = ( Segment ) f ; // c o m p i l a t i o n OK

8 P o i n t p3 = ( P o i n t ) f ; // c o m p i l a t i o n OK ( ! )

Exécution:

Crash du programme avec le message suivant

1 E x c e p t i o n i n t h r e a d " main " j a v a . l a n g . C l a s s C a s t E x c e p t i o n :

2 c o u r s 2 . Segment c a n n o t be c a s t t o c o u r s 2 . P o i n t

3 a t c o u r s 2 . T e s t . main ( T e s t . j a v a : 2 6 )

(13)

Cast: limite

Un système peu sécurisé à la compilation:

1 P o i n t p1 = new P o i n t (" t o t o ", 0 , 2 ) ;

2 P o i n t p2 = new P o i n t ( " t o t o ␣ 2 ", 3 , 2 ) ;

3 F i g u r e f = new Segment ( p1 , p2 ) ;

4

5 F i g u r e f 2 = ( F i g u r e ) p1 ; // OK m a i s i n u t i l e

6 F i g u r e f 3 = p1 ; // OK S u b s o m p t i o n c l a s s i q u e

7 Segment s = ( Segment ) f ;

// c o m p i l a t i o n OK

8 P o i n t p3 = ( P o i n t ) f ; // c o m p i l a t i o n OK ( ! )

Exécution:

Crash du programme avec le message suivant

1 E x c e p t i o n i n t h r e a d " main " j a v a . l a n g . C l a s s C a s t E x c e p t i o n :

2 c o u r s 2 . Segment c a n n o t be c a s t t o c o u r s 2 . P o i n t

3 a t c o u r s 2 . T e s t . main ( T e s t . j a v a : 2 6 )

(14)

Cast: limite

Un système peu sécurisé à la compilation:

1 P o i n t p1 = new P o i n t (" t o t o ", 0 , 2 ) ;

2 P o i n t p2 = new P o i n t ( " t o t o ␣ 2 ", 3 , 2 ) ;

3 F i g u r e f = new Segment ( p1 , p2 ) ;

4

5 F i g u r e f 2 = ( F i g u r e ) p1 ; // OK m a i s i n u t i l e

6 F i g u r e f 3 = p1 ; // OK S u b s o m p t i o n c l a s s i q u e

7 Segment s = ( Segment ) f ; // c o m p i l a t i o n OK

8 P o i n t p3 = ( P o i n t ) f ;

// c o m p i l a t i o n OK ( ! )

Exécution:

Crash du programme avec le message suivant

1 E x c e p t i o n i n t h r e a d " main " j a v a . l a n g . C l a s s C a s t E x c e p t i o n :

2 c o u r s 2 . Segment c a n n o t be c a s t t o c o u r s 2 . P o i n t

3 a t c o u r s 2 . T e s t . main ( T e s t . j a v a : 2 6 )

(15)

Cast: limite

Un système peu sécurisé à la compilation:

1 P o i n t p1 = new P o i n t (" t o t o ", 0 , 2 ) ;

2 P o i n t p2 = new P o i n t ( " t o t o ␣ 2 ", 3 , 2 ) ;

3 F i g u r e f = new Segment ( p1 , p2 ) ;

4

5 F i g u r e f 2 = ( F i g u r e ) p1 ; // OK m a i s i n u t i l e

6 F i g u r e f 3 = p1 ; // OK S u b s o m p t i o n c l a s s i q u e

7 Segment s = ( Segment ) f ; // c o m p i l a t i o n OK

8 P o i n t p3 = ( P o i n t ) f ; // c o m p i l a t i o n OK ( ! )

Exécution:

Crash du programme avec le message suivant

1 E x c e p t i o n i n t h r e a d " main " j a v a . l a n g . C l a s s C a s t E x c e p t i o n :

2 c o u r s 2 . Segment c a n n o t be c a s t t o c o u r s 2 . P o i n t

3 a t c o u r s 2 . T e s t . main ( T e s t . j a v a : 2 6 )

(16)

Cast: avec plusieurs niveaux de hiérarchie

1 // s u b s o m p t i o n

2 F i g u r e f = new Segment ( p1 , p2 ) ;

3 F i g u r e f 2 = new C a r r e ( p1 , c o t e ) ;

4 F i g u r e f 3 = new T r i a n g l e ( p1 , p2 , p3 ) ; ;

5 P o l y g o n e p = new T r i a n g l e ( p4 , p5 , p6 ) ;

6

7 // c a s t OK

8 T r i a n g l e t = ( T r i a n g l e ) p ; // OK ( comme p r e c e d e m m e n t )

9

10 P o l y g o n e p2 = ( P o l y g o n e ) f 2 ; // OK c o m p i l + e x e c :

11 // un C a r r e EST UN P o l y g o n e

12

13 P o l y g o n e p3 = ( T r i a n g l e ) f 3 ; // OK:

14 // f 3 e s t un T r i a n g l e => c o n v e r s i o n OK (JVM)

15 // p3 p e u t r e f e r e n c e r un T r i a n g l e OK ( c o m p i l . )

16

17 // c a s t KO

18 C a r r e c = ( C a r r e ) f ; // KO JVM

19 C e r c l e c = ( C e r c l e ) p ; // KO Compil: opération impossible

(17)

Cast: avec plusieurs niveaux de hiérarchie

1 // s u b s o m p t i o n

2 F i g u r e f = new Segment ( p1 , p2 ) ;

3 F i g u r e f 2 = new C a r r e ( p1 , c o t e ) ;

4 F i g u r e f 3 = new T r i a n g l e ( p1 , p2 , p3 ) ; ;

5 P o l y g o n e p = new T r i a n g l e ( p4 , p5 , p6 ) ;

6

7 // c a s t OK

8 T r i a n g l e t = ( T r i a n g l e ) p ; // OK ( comme p r e c e d e m m e n t )

9

10 P o l y g o n e p2 = ( P o l y g o n e ) f 2 ; // OK c o m p i l + e x e c :

11 // un C a r r e EST UN P o l y g o n e

12

13 P o l y g o n e p3 = ( T r i a n g l e ) f 3 ; // OK:

14 // f 3 e s t un T r i a n g l e => c o n v e r s i o n OK (JVM)

15 // p3 p e u t r e f e r e n c e r un T r i a n g l e OK ( c o m p i l . )

16

17 // c a s t KO

18 C a r r e c = ( C a r r e ) f ; // KO JVM

19 C e r c l e c = ( C e r c l e ) p ; // KO Compil: opération impossible

(18)

Cast: sécurisation Idée

Vérifier le type de l’instance avant la conversion

1 F i g u r e f = new Segment ( p1 , p2 ) ;

2 Segment s ;

3 i f( f i n s t a n c e o f Segment )

4 s = ( Segment ) f ;

⇒ vous utiliserez systématiquement cette sécurisation

Que penser de:

1 // F i g u r e −> P o l y g o n e −> C a r r e

2 F i g u r e f = new C a r r e ( c o t e ) ;

3 P o l y g o n e p ;

4 i f( f i n s t a n c e o f P o l y g o n e )

5 p = ( P o l y g o n e ) f ;

Est ce que ça marche (compil+exec)?

Est ce que ça peut être utile?

(19)

Cast: sécurisation Idée

Vérifier le type de l’instance avant la conversion

1 F i g u r e f = new Segment ( p1 , p2 ) ;

2 Segment s ;

3 i f( f i n s t a n c e o f Segment )

4 s = ( Segment ) f ;

⇒ vous utiliserez systématiquement cette sécurisation Que penser de:

1 // F i g u r e −> P o l y g o n e −> C a r r e

2 F i g u r e f = new C a r r e ( c o t e ) ;

3 P o l y g o n e p ;

4 i f( f i n s t a n c e o f P o l y g o n e )

5 p = ( P o l y g o n e ) f ;

Est ce que ça marche (compil+exec)?

Est ce que ça peut être utile?

(20)

Cast: usage dans equals fonction equals

Il y a toujours un cast (sécurisé) dans equals pour pouvoir accéder aux attributs à comparer

Exemple sur la classe Point:

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 ) { // V1

2 i f (t h i s == o b j )

3 r e t u r n t r u e;

4 i f ( o b j == n u l l)

5 r e t u r n f a l s e;

6 i f ( g e t C l a s s ( ) != o b j . g e t C l a s s ( ) )

7 r e t u r n f a l s e;

8 P o i n t o t h e r = ( P o i n t ) o b j ;

9 i f ( x != o t h e r . x )

10 r e t u r n f a l s e;

11 i f ( y != o t h e r . y )

12 r e t u r n f a l s e;

13 r e t u r n t r u e;

14 }

(21)

getClass vs instanceof

Imaginons la redéfinition suivante pour equals:

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 ) {// V2

2 i f (t h i s == o b j )

3 r e t u r n t r u e;

4 i f ( o b j == n u l l)

5 r e t u r n f a l s e;

6 // i f ( g e t C l a s s ( ) != o b j . g e t C l a s s ( ) ) en V1

7 i f ( ! ( o b j instanceof P o i n t ) )

8 r e t u r n f a l s e;

9 P o i n t o t h e r = ( P o i n t ) o b j ;

10 i f ( x != o t h e r . x )

11 r e t u r n f a l s e;

12 i f ( y != o t h e r . y )

13 r e t u r n f a l s e;

14 r e t u r n t r u e;

15 }

Quel est le défaut de l’implémentation v2?

(22)

Prise en défaut:

1 P o i n t p = new P o i n t ( 1 , 2 ) ;

2 P o i n t T r a f i q u e p2 = new P o i n t T r a f i q u e (" t o t o ", 1 , 2 ) ;

3 i f( p . e q u a l s ( p2 ) )

4 S y s t e m . o u t . p r i n t l n (" i l s ␣ s o n t ␣ e g a u x ␣ ! ! ! ␣ ") ;

5 i f( p2 . e q u a l s ( p ) )

6 S y s t e m . o u t . p r i n t l n (" e t ␣ i c i ␣ ? ? ? ") ;

Avec :

1 p u b l i c c l a s s P o i n t T r a f i q u e e x t e n d s P o i n t {

2 p r i v a t e S t r i n g qqch ;

3 p u b l i c P o i n t T r a f i q u e ( S t r i n g nom , d o u b l e x , d o u b l e y ) {

4 s u p e r( x , y ) ;

5 qqch = nom ; // un a t t r i b u t en p l u s

6 }

7 }

V1: pas d’égalité V2: égalité détectée... Est ce légitime?

Pb: quid de la symétrie?

Références

Documents relatifs

L’archive ouverte pluridisciplinaire HAL, est destinée au dépôt et à la diffusion de documents scientifiques de niveau recherche, publiés ou non, émanant des

We study the complexity of the problems of finding, given a graph G, a largest induced subgraph of G with all degrees odd (called an odd subgraph), and the smallest number of

[ 26 ] and Nguyen and Matias [ 23 ] proposed a randomly weighted kernel estimator of f , where the weights are estimators of the posterior probabilities of the mixture model, that

International Journal of Ambient Energy, Volume 7, Number 4 October 1986 Natural convection in the cavity of a basement block wall.. Goodrich, Institute for Research in

The ITS sequences (approximately 600 bp long with a cleaned section of 484 bp) of the aquatic fungi V3.13 and V3.10B, isolated from surface sterilized needles incubated in the

A series of health problems suffered by an elderly couple soon after they occupied a new 2 4 0 3 3 mobile home and initial measurement of an indoor

Here, therefore, by controlling for low-level local visual motion across stimuli and adding this measure as a covariate to our fMRI analysis we present a method of localizing the

It will be seen later that understanding – or at least describing – precipitation of graphite needs differentiating free growth from the liquid (primary