OVH Cloud OVH Cloud

tester la classe d'un objet

27 réponses
Avatar
yvon.thoravalNO-SPAM
Bonjour,

j'ai un objet, disons "o", qui peut-être soit une String soit une Map,
je ne connais pas la méthode la plus élégante, disons la pus "javaish"
pour tester la classe de cette objet, ce que je fais et qui marche :

j'ai un autre objet "on" qui est toujours une String je fais donc :

String onClass = on.getClass().toString();
par ailleurs :
String oClass = o.getClass().toString();
puis je teste sans pb:

if (onClass.equals(oClass) {
faire ce qu'il faut dans ce cas là...
}

j'ai essayé, sans succès :

if ("java.lang.String".equals(oClass) {...

l'égalité n'est jamais trouvée... ce que je ne comprend pas.

d'où ma question, donc si vous avez des lumières à m'apporter, j'en
serai ravi et vous remercie d'avance...

--
yt

10 réponses

1 2 3
Avatar
yvon.thoravalNO-SPAM
Laurent Bossavit wrote:

A l'exception des méthodes qui surchargent equals(), tester la classe
d'un objet est presque toujours signe d'un défaut de conception.


Fort possible

En l'occurrence, une String et une Map n'ont pas le même contrat, il
semble donc extrêmement étrange de pouvoir les rencontrer dans une même
référence polymorphique.

Es-tu sûr que ta conception actuelle est satisfaisante ?


c'est tout bête mon truc, je pense que ça doit pouvoir beaucoup se
simplifier (j'ai une facheuse tendance à faire simple quand on peut
compliquer °;)

bon, en fait je lis des metadata d'une base de donnée, en particulier
les callableStatements (storedProcedures) en réalité, tout est soit en
String soit en short mais j'ai d'abord :

PROCEDURE_NAME ensuite PROCEDURE_TYPE et REMARKS ces deux derniers
définissant le type de procédure ensuite je fais un
"getProcedureColumns()" pour toutes les colonnes de la procédure
c'est-à-dire toutes les variables d'entrée et/ou de sortie qui ont les
attributs suivants :

COLUMN_NAME
COLUMN_TYPE
TYPE_NAME
PRECISION
LENGTH
SCALE
RADIX
NULLABLE
REMARKS

bien sûr, chaque attribut a une valeur qui est soit un short soit une
String et je veux représenter cela sous forme d'un arbre :

root
valeur de (PROCEDURE_NAME)
PROCEDURE_TYPE : valeur de (PROCEDURE_TYPE)

REMARKS : valeur de (REMARKS)
valeur de (OLUMN_NAME) // pour la 1ère colonne
COLUMN_TYPE : valeur de (COLUMN_TYPE)
...
REMARKS : valeur de (REMARKS)
...
valeur de (OLUMN_NAME) // pour la nième colonne
COLUMN_TYPE : valeur de (COLUMN_TYPE)
...
REMARKS : valeur de (REMARKS)

j'ai une première HashMap qui me donne par la clé une procédure, ensuite
j'ajoute comme valeur de cette procédure des HashMap ayant pour clé le
nom d'une propriété ou le nom d'une variable d'entrée/sortie, dans le
cas d'une propriété, la valeur est une String, dans le cas d'une
variable la valeur est une autre HashMap représentant les différentes
propriétés et leur valeur de cette variable qui sont elles-mêmes soit
des String soit des short.

Voila le pourquoi du test String ou pas car je dois savoir quand
j'ajoute au noeud procédure de mon arbre si j'ai affaire à une feuille
(String) ou à un autre noeud (HashMap) contenant lui-même des feuilles.

Donc je suis d'accord sur le fait que c'est mal conçu, car je me suis
aperçu (je fais tjs compliqué au départ pour faire simple après), qu'au
lieu de gérer des HashMap inutilement au niveau de mon gestionnaire de
base de données, je pourrais traiter cela directement en noeud ce qui
m'éviterait ce test.


L'erreur provient, à mon avis, du fait que j'ai voulu d'abord tester la
partie du programme lisant les metadata de la base de données (sortie à
la console par Sytem.out) puis fabrication d'un arbre avec des :

treePanel.addObject(proceduresNode, procedureName);

treePanel étant une instance d'une classe à moi :

public class TreeShema extends JPanel {
protected DefaultMutableTreeNode rootNode;
protected DefaultTreeModel treeModel;
protected JTree tree;


Et aussi que, pour l'instant, j'ai toujours divisé mes classes en deux
parties :

- 1 - lecture de la base de donnée ;
- 2 - présentation des résultats.

et ça, ça ne me va pas du tout car ca amène des trucs redondants, des
lourdeurs etc...

je souhaite obtenir un design où mes objets java soient le plus proches
possibles des données sql (j'ai regardé un peu ozone pour travailler
directement en oql mais il me semble que je ne suis pas assez compétent,
aujourd'hui, pour piger comment faire aussi, je reste avec une base
relationnelle standard mais implémentée en java : Hypersonic SQL)
--
yt

Avatar
Thibaut Desmarest
Laurent Bossavit wrote:
Thibaut,


instanceof JTextField, instanceof JButton etc... Pour faire des
traitements différents...



Différents de quelle manière ?


Ben par exemple quand j'appuie sur entrée sur un champ de saisie ca
passe le focus au champ suivant. Si je suis sur un bouton ca fait un
doClick(), si je suis sur une JComboBox ca valide le contenu etc...

En gros j'ai ça :

public void keyPressed(KeyEvent ek) {

if(ek.getKeyCode() == KeyEvent.VK_ENTER) {

if(ek.getSource() instanceof JTextArea) {

if(ek.isControlDown())
transfererLeFocus(ek);
}

else if(ek.getSource() instanceof JButton)
((JButton) ek.getSource()).doClick();

else if(ek.getSource() instanceof JComboBox) {
/* Valider le contenu */
transfererLeFocus(ek);
}

else /* Pour tous les autres composants */
transfererLeFocus(ek);
}

P.S: je connais FocusEvent et FocusListener, et je m'en sers d'ailleurs
dans d'autres parties du programme, mais pour faire ce traitement ci je
vois pas trop puisque justement le but est de passer le focus...

Y'avait t'il une manière plus intelligente de procéder ?



Dans la mesure où tu n'as pas la main sur la hiérarchie de classes de
Swing, je n'en mettrais pas ma tête à couper. Normalement, tu remplaces
le test sur la classe par un appel polymorphique.


Hein ?? Désolé masi tu peux préciser s'il te plait ? J'avoue que j'ai
jamais vraiment étudié le polymorphisme alors c'est un mot qui me fait
encore peur... (Si ca se trouve je m'en suis déjà servi sans le savoir :-p )

Dans ce cas précis, tu ne peux pas le faire directement. Il faut utiliser un Decorator (*), ou
alors changer complètement d'algorithme comme le suggère Rémy.

Lorsque tu examines la classe pour déterminer le bon comportement, le
problème que tu créées est le suivant: à chaque fois que tu veux prendre
en compte une nouvelle sous-classe de JComponent dans ta hiérarchie
(mettons que tu rajoutes à ton application un JAudioSampleButton qui te
permet de choisir un son, alors que tu n'en avais pas eu besoin jusqu'à
présent) tu dois ajouter un cas à ton test.


Seulement si le traitement est un cas particulier. Sinon
JAudioSampleButton qui hérite de JButton fera son doClick() comme les
autres. Or, qui dit cas particulier dit de toutes façons du code à rajouter.

Il serait préférable que toutes les modifications nécessaires pour
prendre en compte un JAudioSampleButton soient contenues... dans
JAudioSampleButton, et pas ailleurs.


Là je suis d'accord mais comment tu fais dans ce cas précis ? Tu mets le
code du KeyListener personnalisé dans chaque composant ? Ca veut dire
qu'il faut étendre tous les composants déjà existants et créer
MyJButton, MyJComboBox, MyJTextField etc ? je vois vraiment pas
l'interêt car ça fait encore plus de boulot...

(*) Un exemple de Decorator pour la hiérarchie JComponent:
http://www.onjava.com/pub/a/onjava/2003/02/05/decorator.html

Laurent
http://bossavit.com/thoughts/


Thibaut


Avatar
Laurent Bossavit
Yvon,

Voila le pourquoi du test String ou pas car je dois savoir quand
j'ajoute au noeud procédure de mon arbre si j'ai affaire à une feuille
(String) ou à un autre noeud (HashMap) contenant lui-même des feuilles.


En conception Objet, on va typiquement chercher à représenter les
structures par des classes. On pourrait imaginer une classe Procedure
encapsulant une liste contenant des instances de ProcedureAttribute et
ProcedureColumn.

Laurent

Avatar
yvon.thoravalNO-SPAM
Laurent Bossavit wrote:


En conception Objet, on va typiquement chercher à représenter les
structures par des classes. On pourrait imaginer une classe Procedure
encapsulant une liste contenant des instances de ProcedureAttribute et
ProcedureColumn.


Ouais, mais bon, mon truc, c'est juste une sorte d'aide-mémoire sur les
procédures existantes dans un JTree, si j'ai le temps, je le ferai.
--
yt

Avatar
remy
"Thibaut Desmarest" a écrit dans le message de news:
ckg3r6$9pr$
Laurent Bossavit wrote:
Thibaut,


instanceof JTextField, instanceof JButton etc... Pour faire des
traitements différents...



Différents de quelle manière ?


Ben par exemple quand j'appuie sur entrée sur un champ de saisie ca
passe le focus au champ suivant. Si je suis sur un bouton ca fait un
doClick(), si je suis sur une JComboBox ca valide le contenu etc...

En gros j'ai ça :

public void keyPressed(KeyEvent ek) {

if(ek.getKeyCode() == KeyEvent.VK_ENTER) {

if(ek.getSource() instanceof JTextArea) {

if(ek.isControlDown())
transfererLeFocus(ek);
}

en gros


implement sur chaque compoment interface KeyListener

public class GestionFocus
{
public void transfererLeFocus(..)...
}

public MonBouton extends J....Implement KeyListener
{
GestionFocus gf;
MonBouton()
{
gf=new GestionFocus...
add...
}

public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void keyPressed(KeyEvent e)
{
gf.transfererLeFocus()...
}
}


else if(ek.getSource() instanceof JButton)
((JButton) ek.getSource()).doClick();

else if(ek.getSource() instanceof JComboBox) {
/* Valider le contenu */
transfererLeFocus(ek);
}

else /* Pour tous les autres composants */
transfererLeFocus(ek);
}

P.S: je connais FocusEvent et FocusListener, et je m'en sers d'ailleurs
dans d'autres parties du programme, mais pour faire ce traitement ci je
vois pas trop puisque justement le but est de passer le focus...

Y'avait t'il une manière plus intelligente de procéder ?



Dans la mesure où tu n'as pas la main sur la hiérarchie de classes de
Swing, je n'en mettrais pas ma tête à couper. Normalement, tu remplaces
le test sur la classe par un appel polymorphique.


Hein ?? Désolé masi tu peux préciser s'il te plait ? J'avoue que j'ai
jamais vraiment étudié le polymorphisme alors c'est un mot qui me fait
encore peur... (Si ca se trouve je m'en suis déjà servi sans le savoir
:-p )


Dans ce cas précis, tu ne peux pas le faire directement. Il faut
utiliser un Decorator (*), ou


alors changer complètement d'algorithme comme le suggère Rémy.

Lorsque tu examines la classe pour déterminer le bon comportement, le
problème que tu créées est le suivant: à chaque fois que tu veux prendre
en compte une nouvelle sous-classe de JComponent dans ta hiérarchie
(mettons que tu rajoutes à ton application un JAudioSampleButton qui te
permet de choisir un son, alors que tu n'en avais pas eu besoin jusqu'à
présent) tu dois ajouter un cas à ton test.


Seulement si le traitement est un cas particulier. Sinon
JAudioSampleButton qui hérite de JButton fera son doClick() comme les
autres. Or, qui dit cas particulier dit de toutes façons du code à
rajouter.


Il serait préférable que toutes les modifications nécessaires pour
prendre en compte un JAudioSampleButton soient contenues... dans
JAudioSampleButton, et pas ailleurs.


Là je suis d'accord mais comment tu fais dans ce cas précis ? Tu mets le
code du KeyListener personnalisé dans chaque composant ? Ca veut dire
qu'il faut étendre tous les composants déjà existants et créer
MyJButton, MyJComboBox, MyJTextField etc ? je vois vraiment pas
l'interêt car ça fait encore plus de boulot...

(*) Un exemple de Decorator pour la hiérarchie JComponent:
http://www.onjava.com/pub/a/onjava/2003/02/05/decorator.html

Laurent
http://bossavit.com/thoughts/


Thibaut




Avatar
Laurent Bossavit
Thibaut,

Normalement, tu remplaces
le test sur la classe par un appel polymorphique.


Hein ?? Désolé masi tu peux préciser s'il te plait ? J'avoue que j'ai
jamais vraiment étudié le polymorphisme alors c'est un mot qui me fait
encore peur... (Si ca se trouve je m'en suis déjà servi sans le savoir :-p )


Dans les grandes lignes, ça consiste à remplacer ceci:

Animal unAnimal;
if (unAnimal instanceof Chien)
System.out.println("Ouah");
if (unAnimal instanceof Chat)
System.out.println("Miaou");


...par cela:

public interface Animal
public void crie()

public class Chien implements Animal
public void crie()
System.out.println("Ouah");

public class Chat implements Animal
public void crie()
System.out.println("Miaou");


Animal unAnimal;
unAnimal.crie();


Laurent
http://bossavit.com/thoughts/


Avatar
Laurent Bossavit
Thibaut,

Là je suis d'accord mais comment tu fais dans ce cas précis ? Tu mets le
code du KeyListener personnalisé dans chaque composant ? Ca veut dire
qu'il faut étendre tous les composants déjà existants


C'est juste, et c'est pour ça que je disais que dans ce cas, où tu n'as
pas la main sur la hiérarchie de classes qui t'est imposée par Swing, il
faut une méthode un peu plus rusée.

Avec un Decorator, ou même simplement en utilisant addKeyListener(), tu
peux modifier le comportement des composants standard (JButton, etc.)
sans les sous-classer. Tu vas donc créer une classe de "décoration" pour
chaque comportement spécifique: transférer le focus, convertir en clic,
ou effectuer une validation. C'est la méthode keyPressed() de chaque
décorateur (ou de chaque KeyListener) qui contiendra dans chaque cas le
"bon" traitement.

L'idée, c'est d'avoir non pas une seule méthode keyPressed() qui
dispatche vers les traitements selon le résultat de instanceof, mais N
méthodes keyPressed() - autant qu'il y a de traitements. C'est au moment
de la création des composants, et non pas au moment de recevoir
l'événement, que tu vas "attacher" au composant le bon comportement.

L'avantage que ça apporte, c'est que ça décompose les décisions; ça les
"décentralise" vers les composants. Quand les responsabilités sont ainsi
décomposées, elles sont plus faciles à factoriser. Par exemple, il
serait beaucoup plus facile d'exclure un JTextArea spécifique de la
politique "standard" de passage du focus. Ou de réutiliser cette gestion
du focus dans d'autres fenêtres.

Laurent
http://bossavit.com/thoughts/

Avatar
Thomas Nguyen
On Tue, 12 Oct 2004 13:24:35 +0200, Laurent Bossavit wrote:

Thibaut,

Normalement, tu remplaces
le test sur la classe par un appel polymorphique.


Hein ?? Désolé masi tu peux préciser s'il te plait ? J'avoue que j'ai
jamais vraiment étudié le polymorphisme alors c'est un mot qui me fait
encore peur... (Si ca se trouve je m'en suis déjà servi sans le savoir :-p )


Dans les grandes lignes, ça consiste à remplacer ceci:

Animal unAnimal;
if (unAnimal instanceof Chien)
System.out.println("Ouah");
if (unAnimal instanceof Chat)
System.out.println("Miaou");


...par cela:

public interface Animal
public void crie()

public class Chien implements Animal
public void crie()
System.out.println("Ouah");

public class Chat implements Animal
public void crie()
System.out.println("Miaou");


Animal unAnimal;
unAnimal.crie();


Laurent
http://bossavit.com/thoughts/


Non, ça c'est la spécialisation, pas le polymorphisme. :)


En reprenant ton exemple avec des animaux, et en rajoutant une classe
Maitre:

public class Maitre {
public void nourrir(Chien c) {
System.out.println("donne un os à " + c);
}
public void nourrir(Chat c) {
System.out.println("donne du lait à " + c);
}
}

public void main() {
Maitre m = new Maitre();
Chat minou = new Chat();
Chien medor = new Chien();

m.nourrir(medor); // appelle la première méthode
m.nourrir(minou); // appelle la deuxième méthode
}


Le polymorphisme, c'est qu'on appelle une méthode différente suivant le
type du(des) paramètre(s) passé(s). Ici, on a deux méthodes "nourrir",
une pour le chien et une pour le chat.


Pour tester, voila un code complet et compilable (et qui marche ;) )

public class TestPolymorphisme
{
static class Animal
{
private String _nom;

public Animal(String nom)
{
_nom = nom;
}

public String toString()
{
return _nom;
}
}

static class Chien extends Animal
{
public Chien(String nom)
{
super(nom);
}
}

static class Chat extends Animal
{
public Chat(String nom)
{
super(nom);
}
}

static class Maitre
{
public void nourrir(Chien c)
{
System.out.println("donne un os à " + c);
}

public void nourrir(Chat c)
{
System.out.println("donne du lait à " + c);
}
}

public static void main(String[] args)
{
Maitre m = new Maitre();
Chat minou = new Chat("minou");
Chien medor = new Chien("médor");

m.nourrir(medor); // appelle la première méthode
m.nourrir(minou); // appelle la deuxième méthode
}
}



Avatar
Laurent Bossavit
Thomas,

Non, ça c'est la spécialisation, pas le polymorphisme. :)


Un exemple de code objet va souvent contenir plusieurs techniques.

L'appel à Animal.crie() dans le second exemple est bien un appel
poymorphique, puisqu'il peut, à l'exécution, se traduire par l'appel de
deux implémentations différentes.

m.nourrir(medor); // appelle la première méthode
m.nourrir(minou); // appelle la deuxième méthode


Oui. On parle de deux types de polymorphisme distincts: moi du
polymorphisme d'objet, et ci-dessus, du polymorphisme par surcharge.
Attention: en Java, les règles de ce dernier sont beaucoup moins claires
que celles concernant les appels de méthodes sur un objet.

Laurent
http://bossavit.com/thoughts/

Avatar
remy
re

pour faire simple
le choix de la fct appelee depend du type de l'argument
donc si tu as 2 boutons il faut que tu specialises tes boutons

public class B0 extend JButton Implement KeyListener

{
B0(..)
{
super(...);
add..
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void keyPressed(KeyEvent e)
{
gestionFocus gf =new gestionFocus();
gf.passefocus(e.getSource());
}



}

public class gestionFocus
{

public void passefocus(B0 b)
{
}
public void passefocus(B1 b)
{
}
public void passefocus(B2 b)
{
}
....
}

ou
*********************************
public class gestionFocus extend JButton
{


gestionFocus(..)
{
super(....);
}

public void passefocus(B0 b)
{
...........
}
public void passefocus(B1 b)
{
...............
}
public void passefocus(B2 b)
{
...........
}
....
}
public class B0 extend gestionFocus Implement KeyListener
{
b0(..)
{
super(...);
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void keyPressed(KeyEvent e)
{
passefocus(e.getSource());
}

}

ton pb maintenant c'est de recuperer les autres obj dans ta fct passeFocus

a+ remy
1 2 3