[Java] Mais à quoi sert instanceof ?

Mais à quoi sert instanceof ? [Java] - Java - Programmation

Marsh Posté le 22-02-2003 à 18:10:48    

J'ai decouvert l'existence de cet opérateur il y a peu, mes profs s'étant bien gardé de m'en révéler l'existence (à juste titre je pense) pendant leurs cours de Java.
En fait je m'interroge beaucoup sur l'utilité de cet opérateur. Même si au premier abord il peut paraitre très pratique, je trouve son utilisation dangereuse et souvent contraire aux principes de POO.
Je me demande vraiment pourquoi les concepteurs du langage ont mis cet opérateur, alors si quelqu'un pouvait m'expliquer comment on peut s'en servir, sans tomber dans la bidouille ou flinguer le polymorphisme...

Reply

Marsh Posté le 22-02-2003 à 18:10:48   

Reply

Marsh Posté le 22-02-2003 à 18:16:47    

à connaitre le type d'une variable
 
exemple
 

Code :
  1. public class Truc
  2. {
  3. boolean equals(Object o)
  4. {
  5.   if(o == this)
  6.   {
  7.     return true;
  8.   }
  9.    if(!(o instanceof Truc))
  10.    {
  11.      return false;
  12.    }
  13.   // Ok, le cast est sure
  14.   Truc oo=(Truc)o;
  15.   // et la tu peux comparer tes champs
  16. }
  17. };


 
 

Reply

Marsh Posté le 22-02-2003 à 18:20:42    

++Taz a écrit :

à connaitre le type d'une variable
 
exemple
 

Code :
  1. public class Truc
  2. {
  3. boolean equals(Object o)
  4. {
  5.   if(o == this)
  6.   {
  7.     return true;
  8.   }
  9.    if(!(o instanceof Truc))
  10.    {
  11.      return false;
  12.    }
  13.   // Ok, le cast est sure
  14.   Truc oo=(Truc)o;
  15.   // et la tu peux comparer tes champs
  16. }
  17. };


 
   


Oui d'accord, mais :
- si o est une instance d'une classe dérivée de Truc, (o instanceof Truc) est vrai.
- o.getClass() permet de faire la même chose.

Reply

Marsh Posté le 22-02-2003 à 19:50:50    

R3g a écrit :


Je me demande vraiment pourquoi les concepteurs du langage ont mis cet opérateur, alors si quelqu'un pouvait m'expliquer comment on peut s'en servir, sans tomber dans la bidouille ou flinguer le polymorphisme...


 
En effet :jap:  une bonne conception permet d'eviter l'utilisation cet operateur.  
C'est pratique pour les rustines de dernières minutes  :ange:


---------------
Compromise! Conformity! Assimilation! Submission! Ignorance! Hypocrisy! Brutality! The Elite! All of which are american dreams!
Reply

Marsh Posté le 22-02-2003 à 20:03:49    

Deltanyne a écrit :


 
En effet :jap:  une bonne conception permet d'eviter l'utilisation cet operateur.  
C'est pratique pour les rustines de dernières minutes  :ange:  

en quoi c'est pas objet d'utiliser instanceof ?


---------------
http://runnerstats.net
Reply

Marsh Posté le 22-02-2003 à 20:06:35    

instanceof c pratik kan par exemple tu fait redéfini la méthode equals de la class objet, paske la compilataur bosse avec la classe déclaré et il fau checké la class réeel
 
 
 
ps:vi je parle pas fr

Reply

Marsh Posté le 22-02-2003 à 20:14:45    

R3g a écrit :


- o.getClass() permet de faire la même chose.


 
non, par exemple :
 

Code :
  1. Object o = new Vector();
  2. o instanceof Vector // vrai
  3. o instanceof List // vrai
  4. o.getClass().eqals(Vector.class) // vrai  
  5. o.getClass().eqals(List.class) // faux

Reply

Marsh Posté le 22-02-2003 à 20:15:20    

noldor a écrit :

en quoi c'est pas objet d'utiliser instanceof ?


C'est pas que c'est pas objet en soit, maisca permet très facilement de passer outre l'aspect "transparent" du polymorphisme, et donc je trouve ca dangereux.
 
Epok > deja dit plus haut, je pense que dans ce cas il vaut mieux utiliser la classe Class.

Reply

Marsh Posté le 22-02-2003 à 20:19:54    

benou a écrit :


 
non, par exemple :
 

Code :
  1. Object o = new Vector();
  2. o instanceof Vector // vrai
  3. o instanceof List // vrai
  4. o.getClass().eqals(Vector.class) // vrai  
  5. o.getClass().eqals(List.class) // faux




Ben c'est justement ce que je lui reproche moi. On peut pas savoir pourquoi c'est vrai (c'est la classe qu'on veut ou c'est une classe derivée ?)
Je pense que c'est mieux de :

Code :
  1. Object o = new Vector();
  2. o.getClass().eqals(Vector.class) // vrai  
  3. o.getClass().eqals(List.class) // faux
  4. o.getClass().isAssignableFrom(List.class) // vrai


Reply

Marsh Posté le 22-02-2003 à 20:21:55    

Mais bon je reconnais que dans le cas de equals(), c'est bien pratique. Mais est-ce que c'est plus sale de (c'est ce que je faisais jusqu'à maintenant) faire le cast dans un try et catcher la ClassCastException ?

Reply

Marsh Posté le 22-02-2003 à 20:21:55   

Reply

Marsh Posté le 22-02-2003 à 20:23:04    

isSsignableFrom revient exactement au même que instanceof ...

Reply

Marsh Posté le 22-02-2003 à 20:27:10    

benou a écrit :

isSsignableFrom revient exactement au même que instanceof ...


Oui je reconnais. En fait je commence à revenir sur mes positions. Simplement j'ai été surpris de decouvrir cet operateur. C'est le genre de truc dont je pensais que ca pouvait exister en C++ mais pas en Java. Je continue à croire que ca permet de salement briser le concept objet.

Reply

Marsh Posté le 22-02-2003 à 20:30:54    

ben c'est sur qu'on peut considérer que l'héritage casse l'encapsulation :sweat:  
 
sinon moi je trouve important et sain le comportement de instanceof, encore heureux qu'un vecteur qui implements List, puisse etre considérer comme une list

Reply

Marsh Posté le 22-02-2003 à 20:40:23    

++Taz a écrit :

ben c'est sur qu'on peut considérer que l'héritage casse l'encapsulation :sweat:  
 
sinon moi je trouve important et sain le comportement de instanceof, encore heureux qu'un vecteur qui implements List, puisse etre considérer comme une list


Oui bien sur, presenté comme ca... Bon ok j'admets que j'ai dit une connerie.

Reply

Marsh Posté le 22-02-2003 à 20:45:35    

R3g a écrit :

J'ai decouvert l'existence de cet opérateur il y a peu, mes profs s'étant bien gardé de m'en révéler l'existence (à juste titre je pense) pendant leurs cours de Java.
En fait je m'interroge beaucoup sur l'utilité de cet opérateur. Même si au premier abord il peut paraitre très pratique, je trouve son utilisation dangereuse et souvent contraire aux principes de POO.
Je me demande vraiment pourquoi les concepteurs du langage ont mis cet opérateur, alors si quelqu'un pouvait m'expliquer comment on peut s'en servir, sans tomber dans la bidouille ou flinguer le polymorphisme...


 
C'est surtout utile pour les outils du langage, pas pour les applications, un explorateur par exemple pourrait en avoir besoin, pour des trucs un peu introspectifs etc.
 
En général, j'insulte les gens qui l'utilisent dans leur application, c'est souvent dû à un manque de connaissance, le top c'est le mec qui fait (enfin qui essaye) de faire un Switch sur un getClass ou qui branche sur  instanceof.
 
Tu demandes pas son type à un objet que tu connais pas, tu lui demande de faire une action en tenant compte _ton_ type (quand tu écris une classe, donc que tu choisis un point de vue). Si la relation est réciproque (suivant les actions), tu dois te tenir prêt à répondre à toute demande du même style, éventuellement en renvoyant la politesse.
 

Reply

Marsh Posté le 22-02-2003 à 20:47:54    

nraynaud a écrit :


 
Tu demandes pas son type à un objet que tu connais pas, tu lui demande de faire une action en tenant compte _ton_ type (quand tu écris une classe, donc que tu choisis un point de vue). Si la relation est réciproque (suivant les actions), tu dois te tenir prêt à répondre à toute demande du même style, éventuellement en renvoyant la politesse.
 
 


Ben voila, c'est comme ca que je voyais les choses. Maintenant, c'est vrai que surcharger equals(), compareTo() etc. sans caster l'objet, ca n'a pas de sens.

Reply

Marsh Posté le 22-02-2003 à 21:02:54    

R3g a écrit :


Ben voila, c'est comme ca que je voyais les choses. Maintenant, c'est vrai que surcharger equals(), compareTo() etc. sans caster l'objet, ca n'a pas de sens.


 
Si t'es dans un domaine métier, tu utilises les fonctions métier, pas les fonctions de la classe Object, tu auras un typage beaucoup plus fin -> sécurité, rapidité. Comparer un MonAppInteger avec UnMonAppBigInteger par equals() me parraît un peu fumeux sachant la tronche du contrat de equals().
 
D'autre part, quand-bien même equals() nécessiterait une bidouille pour fonctionner (je la sens mal depuis le début cette fonction, vivement les generics corrects), c'est très loin d'être la majorité des cas.

Reply

Marsh Posté le 22-02-2003 à 21:07:06    

nraynaud a écrit :


 
Si t'es dans un domaine métier, tu utilises les fonctions métier, pas les fonctions de la classe Object, tu auras un typage beaucoup plus fin -> sécurité, rapidité. Comparer un MonAppInteger avec UnMonAppBigInteger par equals() me parraît un peu fumeux sachant la tronche du contrat de equals().
 
D'autre part, quand-bien même equals() nécessiterait une bidouille pour fonctionner (je la sens mal depuis le début cette fonction, vivement les generics corrects), c'est très loin d'être la majorité des cas.  


C'est sur, seulement quand tu surcharges equals dans MonAppInteger, tu sais pas par quel abruti ta classe va pouvoir utilisée, alors il vaut mieux prendre des précautions.

Reply

Marsh Posté le 22-02-2003 à 22:11:49    

R3g a écrit :


C'est sur, seulement quand tu surcharges equals dans MonAppInteger, tu sais pas par quel abruti ta classe va pouvoir utilisée, alors il vaut mieux prendre des précautions.


 
Le problème vient du fait que equals n'a rien à foutre dans object, mais sans equals, pas de collections. Donc re-vivement des generics, le pb, ça va être que maintenant, ils vont vouloir être compatibles au niveau source et ça va encore être un fossile qui va traîner dans le langage.
 
Je viens de regarder eiffel :
1) il possède la même méthode, typée plus finement (like Current)
2) le système de types ne permet pas vraiment de faire fondamentalement mieux que java (un peu mais pas beaucoup) en polymorphisme.
3) Il utilise la même merde que java au niveau des collections (l'égalité de Any), je suis déçu.
4) il propose une tentative d'affectation dans un cas simulaire dans son bouquin (p.622).

Reply

Marsh Posté le 23-02-2003 à 01:41:56    

moi-même a écrit :


plein de trucs super intéressants


 
De toute façon, même s'il a fait largement progresser l'informatique,je pense que je vais aller mettre une beigne moi-même à Meyer. Il a pas fait que ça comme conneries.


Message édité par nraynaud le 23-02-2003 à 01:48:24
Reply

Marsh Posté le 24-02-2003 à 10:29:23    

Quid de Ada ? (ce n'est pas un troll, mais une vraie question)
Ses concepteurs avaient pris des partis pris assez originaux sur certains points. Par exemple :
 
Les types dits privés ont un opérateur d'affectation et d'égalité implicites, alors que les types limités privés n'en ont pas (mais seul l'opérateur d'égalité peut être redéfini en tant qu'opérateur en Ada). Les arguments de ces opérateurs sont toujours strictement typés (exemple : "function operator=(left : Complex; right : Complex) returns boolean" ).
 
Par ailleurs, quand une classe "Mere" a une méthode à 2 arguments de type "Mere", sa sous-classe fille hérite d'une méthode à 2 arguments de type "Fille" (autrement dit, l'héritage ne porte pas que sur le type de l'objet receveur, mais potentiellement sur le type de tous les arguments).

Reply

Marsh Posté le 24-02-2003 à 14:57:39    

J'aurais trouvé une utilisation de instanceOf.
 
Le contexte (mais c'est un détail), c'est celui de la création d'un value object (VO) en utilisant la stratégie value object factory (oui, je sais, ça fait pompeux comme ça...)
Le principe consiste à utiliser la reflection pour copier les champs de ClassA dans ClassAVO. Un peu de code...
 

Code :
  1. Class ValueObjectFactory()
  2. {
  3.         public static ValueObject makeValueObject(Object source, Class destClass)
  4.         {
  5.                 Object dest = dest.newInstance();
  6.                 // on prend les champs de source
  7.                 // et si dest a un champ du même nom
  8.                 // on copie la valeur de source dans dest
  9.                 return dest;
  10.         }
  11. }
  12. Interface VOMaker
  13. {
  14.         ValueObject getValueObject()
  15. }
  16. Class ClassAVO {...}
  17. Class ClassA implements VOMaker
  18. {
  19.         public ClassDependent dependent;
  20.         public ValueObject getValueObject()
  21.         {
  22.                 return makeValueObject(this, ClassAVO.class)
  23.         }
  24. }
  25. Class ClassDependentVO {...}
  26. Class ClassDependent implements VOMaker
  27. {
  28.         ...
  29. }


 
Par contre, je ne veux pas recopier la valeur dependent, mais créer un VO à partir de dépendent.  
Donc avant de copier le champ, je vérifie si il est instanceOf de VOMaker pour savoir si je peux créer un VO.
 
Vous en pensez quoi ?
 
 
 
 
 
------------------
 
Pour ceux que ça interesse, je me base sur le code généré par Together pour ce pattern
 

Code :
  1. public static Serializable createValueObject(Object ejb, String whichVOType, String completeVOType) {
  2.         try {
  3.             // Get the class data for the complete
  4.             // value object type
  5.             ClassData cData = getClassData(completeVOType);
  6.             // Get class data for the requested VO type
  7.             ClassData voCData = getClassData(whichVOType);
  8.             // Create the value object of the requested
  9.             // value object type...
  10.             java.lang.Object whichVO = Class.forName(whichVOType).newInstance();
  11.             // get the VO fields for the requested VO
  12.             // from the ClassData for the requested VO
  13.             java.lang.reflect.Field[] voFields = voCData.arrFields;
  14.             // get all fields for the complete VO
  15.             // from the ClassData for complete VO
  16.             java.lang.reflect.Field[] beanFields = cData.arrFields;
  17.             // copy the common fields from the complete VO
  18.             // to the fields of the requested VO
  19.             for (int i = 0; i < voFields.length; i++) {
  20.                 try {
  21.                     String voFieldName = voFields[i].getName();
  22.                     for (int j = 0; j < beanFields.length; j++) {
  23.                         // if the field names are same, copy value
  24.                         if (voFieldName.equals(beanFields[j].getName())) {
  25.                             // Copy value from matching field
  26.                             // from the bean instance into the new
  27.                             // value object created earlier
  28.                             voFields[i].set(whichVO, beanFields[j].get(ejb));
  29.                             break;
  30.                         }
  31.                     }
  32.                 } catch (Exception e) {
  33.                     // handle exceptions that may be thrown
  34.                     // by the reflection methods...
  35.                 }
  36.             }
  37.             // return the requested value object
  38.             return (java.io.Serializable) whichVO;
  39.         } catch (Exception ex) {
  40.             // Handle all exceptions here...
  41.         }
  42.         return null;
  43.     }


 
edit : correction des tabulations foireuses + balise cpp


Message édité par _gtm_ le 24-02-2003 à 15:10:44
Reply

Marsh Posté le 24-02-2003 à 14:59:24    

Remplace tes balises "code" par des balises "cpp", on lira meixu ton code... ;)

Reply

Marsh Posté le 24-02-2003 à 17:58:58    

moi je m'en sers justement à cause du polymorphisme...
si tu as des objets totalement hétérogène dans une liste, tu dois les tester avec instanceof

Code :
  1. Object t = liste.get(i)
  2. if (t instanceof Truc){
  3.    return ((Truc)t).getVariableTruc();
  4. }
  5. if (t instanceof Bidule){
  6.    return ((Bidule)t).toString()
  7. }


 
tu vas me dire qu'on pourrait utiliser la même méthode pour les deux objets, et je te réponds que quand les classes existent, tu t'amuse pas à en dériver juste pour une méthode...
 
mais je suis pas un hardcore coder  [:flclsd]

Reply

Marsh Posté le 24-02-2003 à 18:14:05    

Predicator a écrit :

moi je m'en sers justement à cause du polymorphisme...
si tu as des objets totalement hétérogène dans une liste, tu dois les tester avec instanceof

Code :
  1. Object t = liste.get(i)
  2. if (t instanceof Truc){
  3.    return ((Truc)t).getVariableTruc();
  4. }
  5. if (t instanceof Bidule){
  6.    return ((Bidule)t).toString()
  7. }


 


 
Ben à ta place je serais tenté de redéfinir truc.toString pour qu'elle retourne getVariableTruc.
Bon bien sûr si truc est une interface, il faudrait utiliser une class abstraite entre ton interface et tes implémentations, mais parfois on a la flemme :D

Reply

Marsh Posté le 24-02-2003 à 18:25:21    

_gtm_ a écrit :


 
Ben à ta place je serais tenté de redéfinir truc.toString pour qu'elle retourne getVariableTruc.
Bon bien sûr si truc est une interface, il faudrait utiliser une class abstraite entre ton interface et tes implémentations, mais parfois on a la flemme :D


 
c'est bien ce que je dis...
Truc et Bidule sont des classes existantes de Java...
par exemple, Truc = JTextField et Bidule = JComboBox...
tu as donc
 

Code :
  1. ((JTextField)objet).getText();


 
et
 

Code :
  1. ((JComboBox)objet).getSelectedItem().toString();


 
tu vas pas t'amuser à dériver toutes les classes que tu utilises si ?  [:spamafote]


Message édité par Predicator le 24-02-2003 à 18:25:55
Reply

Marsh Posté le 24-02-2003 à 18:55:12    

J'ai pas tout lu, je connais pas JAVA et encore moins InstanceOf, mais :

Citation :

public class Truc
  {
     
    boolean equals(Object o)
    {
        if(o == this)
        {
            return true;
        }
       
         if(!(o instanceof Truc))
         {  
             return false;
         }
       
        // Ok, le cast est sure
        Truc oo=(Truc)o;
        // et la tu peux comparer tes champs
    }
  };

 
Pourquoi accepter le type Object si c'est pour juste apres l'ignorer ?
C'est pas plus simple de remplacer par
boolean equals(Truc o) ?


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 24-02-2003 à 19:00:53    

HelloWorld a écrit :

J'ai pas tout lu, je connais pas JAVA et encore moins InstanceOf, mais :

Citation :

public class Truc
  {
     
    boolean equals(Object o)
    {
        if(o == this)
        {
            return true;
        }
       
         if(!(o instanceof Truc))
         {  
             return false;
         }
       
        // Ok, le cast est sure
        Truc oo=(Truc)o;
        // et la tu peux comparer tes champs
    }
  };

 
Pourquoi accepter le type Object si c'est pour juste apres l'ignorer ?
C'est pas plus simple de remplacer par
boolean equals(Truc o) ?


si il fait comme tu dis, ça surcharge plus la méthode equals de Object


---------------
http://runnerstats.net
Reply

Marsh Posté le 24-02-2003 à 19:05:00    

HelloWorld a écrit :

J'ai pas tout lu, je connais pas JAVA et encore moins InstanceOf, mais :

Citation :

public class Truc
  {
     
    boolean equals(Object o)
    {
        if(o == this)
        {
            return true;
        }
       
         if(!(o instanceof Truc))
         {  
             return false;
         }
       
        // Ok, le cast est sure
        Truc oo=(Truc)o;
        // et la tu peux comparer tes champs
    }
  };

 
Pourquoi accepter le type Object si c'est pour juste apres l'ignorer ?
C'est pas plus simple de remplacer par
boolean equals(Truc o) ?


C'est parce que tu connais pas Java. En java, toutes les classes dérivent implicitement de la classe Object. Et Object possède une méthode equals(Object). Donc equals peut etre appelée sur n'importe quel objet. Il est donc souvent nécessaire de la surcharger pour les classes que tu crée, et il faut que ta méthode aie la meme signature.
Le vrai problème est, comme ca a été dit plus haut, que la présence de cette methode dans la classe Object est plus que discutable.

Reply

Marsh Posté le 20-02-2012 à 12:49:17    

Bonjour les gens,  
J'ai un problème à vous soumettre concernant le instanceof. Pour le moment, je ne vois pas comment faire autrement.
 
Données du problème :
J'ai une class A. (code figé)
J'ai une classe B extends A. (code figé)
J'ai une classe C (structure et héritage figés) avec une méthode "doMyWork" (signature figée) appelée par un environnement au code figé.
Ma méthode "doMyWork" prend en paramètre un Set<A> et doit faire un traitement sur tous les B.
Dernière info : je n'ai pas le droit de modifier l'architecture existante : je dois me débrouiller dans cette classe.
 
Dans le code, je boucle sur mon set, et pour chaque (elt instanceof B), j'effectue mon action.
 
J'utiliserai bien une autre écriture de mon test, mais quel en serait l'avantage par rapport à l'opérateur natif ?  
Est-ce juste parce que ça ne paraît pas propre ou y a-t-il une vraie raison technique derrière ?  
Quel danger instanceof représente ?
Quel perte de performance entraine son utilisation ? (a-t-elle été mesurée ? dans quelles conditions ?)
Une foix transformé en ByteCode, comment êtes-vous certains de la différence que fait "un code équivalent" à instanceof ?
 
Quelqu'un peut-il justifier un autre choix ?
 
Dernière remarque : lorsque vous n'êtes pas maître de l'architecture et que vous ajoutez une crotte de mouche sur le dos d'un éléphant ...
Alors attention aux critiques rapides svp.

Reply

Marsh Posté le 20-02-2012 à 14:43:13    

Techniquement, il n'y a aucun problème à utiliser "instanceof". C'est parfaitement sûr et fiable, et ça ne pose pas de problème particulier niveau perf. C'est même certainement le moyen le plus performant de tester si un objet est bien une instance d'une classe donnée (le compilateur JIT de la VM est souvent capable d'optimiser ça, au contraire des méthodes à base de .getClass().getName() ou autre)
 
Le problème qu'il peut y avoir, c'est que son utilisation peut révéler une mauvaise conception de son logiciel (par exemple, une mauvaise exploitation du polymorphisme). Mais quand il s'agit de s'interfacer avec un système qu'on ne contrôle pas, on fait ce qu'on peut pour que ça marche, même si ce n'est pas toujours très propre.  
 
PS : c'est sympa de déterrer ce topic juste à temps pour qu'il puisse fêter son neuvième anniversaire :)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed