Accueil de l'archive Service proposé par Hervé AGNOUX

TOUT -|- TOUT sur le visuel -|- TOUT sur la logistique

Date sent:      	Fri, 16 Feb 2001 12:20:05 +0100
From:           	wmatter <wmatter@nagora.com>
Send reply to:  	wmatter@nagora.com
Organization:   	Nagora Communication
To:             	"java@u-strasbg.fr" <java@u-strasbg.fr>
Subject:        	Cast d'un type non connu

Avec la Reflection, je sais invoquer une méthode sur un objet de type
MyObjet. J'ai implémenté cette classe, avec de nombreux accesseurs. Je
veux donc invoquer un accesseur getter sur un objet myObjet de type
MyObjet pour récupérer une de ses propriétés resultat (qui est une String)

  //objet cible de type MyObject
  Class c = MyObject.class;
  //déclaration de l'accesseur
  java.lang.reflect.Method getterMethod;

  //pas de parametres 
  Class[] parameterTypes = null;
  //pas d'arguments
  Object[] arguments = null;

  //methodDescription décrit la méthode à appeler : "getName", ou autre
accesseur implémenté
  String methodDescription = "getName";
  getterMethod = c.getMethod(methodDescription, parameterTypes);
  String resultat = (String) getterMethod.invoke( (MyObject)myObjet ,
arguments);

Le code ci dessus fonctionne (j'ai épargné les catch d'exception)
L'avantage est que je peux récupérer une propriété des objets
instanciés,
propriété non déterminée avant le runtime, et décrite dans un fichier
config.

PRB : en fait, mes objets myObjet instanciés ne sont pas tous de mon
type "maison"
MyObject, il y a plusieurs type différents (MyCar, MyBoot...)
étendant MyObject.

Je sais comment récupérer la Class c 
(je connais le type de myObject dans une chaine "MyCar","MyBoot"...)
Class c = Class.forName("MyCar"); etc etc

Mon problème est dans le casting
  String result = (String) getterMethod.invoke( (MyObject)myObjet ,
arguments);
puisque le type MyObject n'est pas connu à l'avance.
Je cherche le moyen de faire à la volée 
String result = (String) getterMethod.invoke( (MyCar)myObjet ,
arguments);
ou
String result = (String) getterMethod.invoke( (MyBoot)myObjet ,
arguments);

Et après avoir fait le tour,
j'ai l'impression que l'API Reflection ne m'offre pas les outils
pour résoudre mon problème.

Qui peut me donner tort?

willfried Matter

     

Date sent:      	Fri, 16 Feb 2001 14:38:51 +0100
To:             	wmatter@nagora.com, java@u-strasbg.fr
From:           	Stéphane PIEL <stephane.piel@softeam.fr>
Subject:        	Re: Cast d'un type non connu
Send reply to:  	java@u-strasbg.fr

At 12:20 16/02/01, you wrote:
..
>Mon problème est dans le casting
>   String result = (String) getterMethod.invoke( (MyObject)myObjet ,
>arguments);
>puisque le type MyObject n'est pas connu à l'avance.
>Je cherche le moyen de faire à la volée
>String result = (String) getterMethod.invoke( (MyCar)myObjet ,
>arguments);
>ou
>String result = (String) getterMethod.invoke( (MyBoot)myObjet ,
>arguments);

Pourquoi caster ? La méthode invoke attend en premier argument une 
référence sur un Objet, pas un MyObject, ni MyCar,.... Si le type réel de
l'instance ne correspond pas à la méthode que tu appeles, invoke lancera
une ClassCastException (cf doc)

>Et après avoir fait le tour,
>j'ai l'impression que l'API Reflection ne m'offre pas les outils
>pour résoudre mon problème.

Y'a pas de problème ;-)


>Qui peut me donner tort?
>
>willfried Matter

-- 
Stephane PIEL - SOFTEAM Ouest - Agence de Rennes
mailto:stephane.piel@softeam.fr

-- 
Exceptionnel !  Votre atelier UML Professionnel GRATUIT !
Telechargez le depuis notre site http://www.objecteering.com

SOFTEAM
------- Think Object


     

Date sent:      	Fri, 16 Feb 2001 15:21:51 +0100
From:           	wmatter <wmatter@nagora.com>
Send reply to:  	wmatter@nagora.com
Organization:   	Nagora Communication
To:             	java@u-strasbg.fr
Subject:        	Re: Cast d'un type non connu

D'abord mes remerciements pour avoir étudié mon problème.

> >Je cherche le moyen de faire à la volée
> >String result = (String) getterMethod.invoke( (MyCar)myObjet ,
> >arguments);
> >ou
> >String result = (String) getterMethod.invoke( (MyBoot)myObjet ,
> >arguments);
> 
> Pourquoi caster ? La méthode invoke attend en premier argument une
> référence sur un Objet, pas un MyObject, ni MyCar,.... Si le type réel
> de l'instance ne correspond pas à la méthode que tu appeles, invoke
> lancera une ClassCastException (cf doc)

C'est bien mon problème.
La méthode invoquée est un accesseur de MyCar (extends MyObjet)
ou de MyBoot (extends MyObjet),
mais pas un accesseur applicable au type MyObject.
J'ai donc effectivement une ClassCastException.

J'ai (temporairement) contourné le problème à cette heure avec un code
basique 

  //j'ai implémenté un getType() dans la classe MyObject qui renvoie une
String
  if ( objet.getType().equals("MyCar") )
  {
   result = (String) getterMethod.invoke( (MyCar)objet , null);
  }
  else if ( objet.getType().equals("MyBoot") )
  {
  result = (String) getterMethod.invoke( (MyBoot)objet , null);
  }
  ...etc etc

Ca fonctionne.
Je décris dans un fichier XML les methodes getterMethod à appliquer à
chaque type, et c'est appliqué au runtime.

Merci encore.

willfried

     

From:           	"Herve AGNOUX" <hagnoux@mail.club-internet.fr>
To:             	wmatter@nagora.com, "java@u-strasbg.fr" <java@u-strasbg.fr>
Date sent:      	Fri, 16 Feb 2001 16:18:25 +0100
Subject:        	Re: Cast d'un type non connu
Send reply to:  	"java@u-strasbg.fr" <java@u-strasbg.fr>
Priority:       	normal

Le 16 Feb 01, wmatter a écrit :

> 
> Et après avoir fait le tour,
> j'ai l'impression que l'API Reflection ne m'offre pas les outils
> pour résoudre mon problème.
> 
> Qui peut me donner tort?
> 

Personne, à mon avis : tu as raison :-)

Je vois deux façons d'éviter ce problème, si problème il y a.

Premièrement, nous dire à quoi ça sert et ce que tu veux en faire. 
Si l'on te suit, on se retrouve avec ce genre d'expression :

<objet inconnu> = (<cast générique>)<expression inconnue>;

C'est un peu vague ! Si tu pars de quelque chose que tu ne 
connais pas pour obtenir ce que tu ne sais pas, comment veux-tu 
savoir le faire !? Il me semble qu'il faudrait connaitre au moins l'un des
tenants et aboutissants ?

Si vraiment ton objet est inconnu, alors c'est simple. La seule 
déclaration que tu puisses faire est :

Object o = <expression inconnue>;

Si, à un moment ou à un autre tu veux le spécialiser, alors 
forcément, à mon avis, à ce moment là tu connais son type, et tu 
peux exprimer le cast. C'est de cette façon que procèdent les 
langages de script style Basic, même si apparemment il n'y a pas 
besoin de typer les objets. Ils "découvrent" au fur et à mesure du 
déroulement du programme le type des données qu'ils manipulent, 
et agissent en conséquence.

L'autre approche est de passer en paramètre de méthode un objet 
destination. Le cast est alors implicite. Mais il faut alors être 
capable de mapper l'objet source vers l'objet l'objet destination. 
Java, à ma connaissance, ne connait pas ce principe, sauf pour les 
tableaux. Il faut te le faire en perso, avec une interface. Je ne sais pas
si c'est vraiment utile.


--
Hervé AGNOUX  hagnoux@mail.club-internet.fr
Faites vos sites avec des formulaires electroniques :
http://www.diaam.com

     

Date sent:      	Fri, 16 Feb 2001 16:56:06 +0100
From:           	wmatter <wmatter@nagora.com>
Send reply to:  	wmatter@nagora.com
Organization:   	Nagora Communication
To:             	"java@u-strasbg.fr" <java@u-strasbg.fr>
Subject:        	Re: Cast d'un type non connu

> Premièrement, nous dire à quoi ça sert et ce que tu veux en faire.
> Si l'on te suit, on se retrouve avec ce genre d'expression :
> 
> <objet inconnu> = (<cast générique>)<expression inconnue>;

Non, c'est
(String) = (<cast générique>) <expression lue dans fichier config>;

> C'est un peu vague ! Si tu pars de quelque chose que tu ne
> connais pas pour obtenir ce que tu ne sais pas, comment veux-tu
> savoir le faire !? Il me semble qu'il faudrait connaitre au moins l'un
> des tenants et aboutissants ?

Exact.

En fait j'ai des instances objet myObjet mappées à partir de champs de
tables SGBDR (avec castor par ailleurs). A priori je ne connais pas le
type de chaque instance : une des sous classes (MyCar, MyBoot de
MyObject). Mais les accesseurs à utiliser pour chaque type MyCar, MyBoot
etc etc sont décrits dans un fichier config (xml). C'est sur cette base
que se pose mon prb.

Je veux faire un système qui permettent d'extraire de l'info de mes
objets,
la nature de l'info étant réglée par fichier de configuration.

L'approche objet n'est pas satisfaisante,
lors de l'extension de l'appli j'attaquerai directement le SGBD
pour connaitre mes informations.
Je cherche uniquement à récupérer des String au final...

willfried Matter

     

From:           	"Herve AGNOUX" <hagnoux@mail.club-internet.fr>
To:             	wmatter@nagora.com, "java@u-strasbg.fr" <java@u-strasbg.fr>
Date sent:      	Sat, 17 Feb 2001 08:24:49 +0100
Subject:        	Re: Cast d'un type non connu
Priority:       	normal
Send reply to:  	java@u-strasbg.fr

Le 16 Feb 01, wmatter a écrit :

> 
> En fait j'ai des instances objet myObjet mappées à partir de champs de
> tables SGBDR (avec castor par ailleurs). A priori je ne connais pas le
> type de chaque instance : une des sous classes (MyCar, MyBoot de
> MyObject). Mais les accesseurs à utiliser pour chaque type MyCar, MyBoot
> etc etc sont décrits dans un fichier config (xml). C'est sur cette base
> que se pose mon prb.
> 

J'ai toujours un peu de mal à comprendre.

Si tu as une méthode d'accés différente pour chaque classe, alors 
je ne vois pas comment tu peux éviter la série de "if else" que tu 
avais donné en exemple, pour selectionner le bon traitement de la 
bonne classe. On pourrait aussi utiliser pour les if 
Class.isAssignableFrom(...), ou Class.isInstance(...), ou même 
object.getClass() == MyClass...

A priori tu peux le faire une fois pour toute au lancement de l'appli.  Tu
ranges la relation classe / accesseur dans une hashtable et ensuite tu
n'as plus qu'à activer la relation, il me semble ? C'est ça que tu
voudrais ?

Ce que je ne comprends pas, c'est si toutes tes classes héritent 
d'une même classe mère, et si tu peux toi même piloter le code de 
ces classes, ou s'il t'est imposé ?

Et je ne comprends toujours pas à quoi sert le cast à (MyCar) 
dans "result = (String) getterMethod.invoke( (MyCar)objet , null);" 
J'ai l'impression que tu considères que le cast transforme l'objet ?

Et autre chose que je ne comprends pas, c'est quel est le rôle du 
String que tu veux obtenir ? Est-ce que cela pourrait être tout autre
chose, ou a-t-il un rôle pour retrouver tes données dans la base plus tard
?


--
Hervé AGNOUX  hagnoux@mail.club-internet.fr
Faites vos sites avec des formulaires electroniques :
http://www.diaam.com


C'est fini ! Retour à l'accueil de la pseudo-archive