73 votes

Est-ce que instanceof est considéré comme une mauvaise pratique ? Si oui, dans quelles circonstances l'instanceof est-elle encore préférable ?

Au fil des ans, j'ai essayé d'éviter instanceof chaque fois que cela est possible. En utilisant le polymorphisme ou le modèle visiteur lorsque c'est possible. Je suppose que cela facilite simplement la maintenance dans certaines situations... Y a-t-il d'autres inconvénients dont il faut être conscient ?

Je le vois cependant ici et là dans les bibliothèques Java, je suppose donc qu'il a sa place ? Dans quelles circonstances est-il préférable ? Est-il jamais inévitable ?

1 votes

J'ai étudié ce même sujet à d'autres fins et j'ai trouvé que les références suivantes étaient vraiment bonnes. - Préférer le polymorphisme à l'instanceof et au downcasting - instanceof versus getClass dans les méthodes d'égalité (Entretien avec Josh Bloch) - Polymorphisme et interfaces (voir la section Quand utiliser instanceof)

23voto

Alexander Pogrebnyak Points 24964

Il a définitivement sa place dans une mise en œuvre de stock de equals . Par exemple

public boolean equals ( Object o )
{
  if ( this == o )
  {
     return true;
  }

  if ( ! (o instanceof MyClass) )
  {
    return false;
  }

  // Compare fields
  ...
}

Une chose intéressante à savoir sur instanceof est que son LHS peut être null et dans ce cas, l'expression est évaluée à false .

1 votes

que me donne la chair de poule depuis plus de 10 ans dans la base de code avec laquelle je dois travailler. L'égalité ne devrait pas être définie (dans la plupart des cas) sur le type d'objets, mais sur leur comportement. MyClass est une implémentation qui peut se comporter de manière totalement égale comme, par exemple, un frère ou une sœur. CacheMyClass objet ! J'aimerais pouvoir vous le donner à 2 :) Hmmm.... à moins que instanceof signifie "met en œuvre" dans ce cas, auquel cas elle mai ont un sens...

7 votes

Je trouve l'utilisation de "instanceof" dans equals() acceptable car il est impossible d'étendre une classe instanciable et d'ajouter un aspect (par exemple, un nouveau champ) tout en préservant le contrat equals() (en particulier la symétrie et la transitivité). Voir "Effective Java" de Bloch.

8 votes

Je préfère getClass() == o.getClass() . Sinon, un Dog peut accidentellement être égal à un Pug même si le Pug n'est pas égal à la Dog . Si la classe est finale instanceof fonctionne bien sûr, mais cela équivaut de toute façon à une comparaison de classes.

15voto

PhiLho Points 23458

Je peux imaginer certains cas, par exemple vous avez des objets d'une bibliothèque, que vous ne pouvez pas étendre (ou qu'il ne serait pas pratique de le faire), peut-être mélangés avec certains de vos objets, tous avec la même classe de base, ensemble dans une collection.
Je suppose que dans ce cas, l'utilisation de instanceof pour distinguer certains traitements sur ces objets pourrait être utile.

Idem dans le cadre de la maintenance d'un code existant, où l'on ne peut pas injecter un nouveau comportement dans un grand nombre de classes anciennes, juste pour ajouter une nouvelle petite fonctionnalité ou corriger un bug...

8 votes

Je pense qu'en général, instanceof est plus utile lorsqu'il s'agit d'API ou de bibliothèques que vous ne contrôlez pas.

2 votes

Ok, donc à cause de l'héritage du code. C'est juste. Pourtant, on a l'impression qu'une telle utilisation de l'instanceof "corrige" des décisions de conception qui n'ont pas été complètement réfléchies.

13voto

Daniel Dolz Points 1443

Je pense que lorsqu'on a absolument besoin de connaître le type d'un objet, instanceof est la meilleure option disponible.

Une mauvaise pratique serait d'avoir beaucoup de instanceof s, l'un à côté de l'autre, et en fonction d'eux, appeler différentes méthodes des objets (bien sûr, le casting). Cela indiquerait probablement que la hiérarchie doit être repensée et probablement refactorée.

6voto

eljenso Points 7690

Lorsque vous êtes à l'intérieur d'un modèle OO pur, alors instanceof est définitivement une odeur de code.

Si, toutefois, vous n'utilisez pas un modèle 100% OO ou si vous devez y injecter des éléments depuis l'extérieur, alors instanceof ou ses équivalents ( isXXX() , getType() ...) peut avoir son utilité.

La "règle" générale serait de l'éviter autant que possible, surtout lorsque vous contrôlent la hiérarchie des types et peuvent utiliser le polymorphisme des sous-types par exemple. L'idée n'est pas de demander à l'objet quel est son type et d'en faire quelque chose, mais plutôt de demander à l'objet directement ou indirectement via un Visiteur (essentiellement le double polymorphisme) d'effectuer une certaine action.

2voto

Joonas Pulakka Points 20361

Il peut être utilisé comme un contrôle d'intégrité avant le casting ; en plus de vérifier que votre objet est du bon type, il vérifie également qu'il n'est pas nul.

if (o instanceof MyThing) {
    ((MyThing) o).doSomething(); // This is now guaranteed to work.
} else {
    // Do something else, but don't crash onto ClassCast- or NullPointerException.
}

1 votes

Je sais très bien ce qu'il fait. Je dirais que votre exemple montre une mauvaise pratique de instanceof. Je voudrais probablement éliminer ce conditionnel en utilisant le polymorphisme tel que décrit aquí

3 votes

@aioobe dans equals(Object o) vous ne savez pas :)

0 votes

Eh bien, l'exemple de ce lien est (en plus d'être excessivement complexe) sujet à un simple crash de nullpointer. Je préfère les solutions simples et robustes aux mots fantaisistes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X