Au fil des ans, j'ai essayé d'éviter instanceof
autant que possible. Utilisation du polymorphisme ou du modèle de visiteur, le cas échéant. Je suppose que cela facilite simplement la maintenance dans certaines situations ... Y at-il d’autres inconvénients dont il faut être conscient?
Je le vois cependant ici et là dans les bibliothèques Java alors je suppose qu'il a sa place? Dans quelles circonstances est-il préférable? Est-ce jamais inévitable?
J'imagine que dans certains cas, par exemple, vous avez des objets d'une bibliothèque que vous ne pouvez pas étendre (ou il serait incommode de le faire), peut-être mélangés avec certains objets de votre bibliothèque, tous avec la même classe de base, dans un collection.
Je suppose que dans ce cas, utiliser instanceof pour distinguer certains traitements sur ces objets pourrait être utile.
Idem dans certaines opérations de maintenance du code hérité où vous ne pouvez pas injecter un nouveau comportement dans de nombreuses anciennes classes simplement pour ajouter une nouvelle fonctionnalité ou une solution de bogue ...
Il a définitivement sa place dans une implémentation 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 exempleof est que son LHS peut être null
et dans ce cas l'expression est évaluée à false
.
Je pense que lorsque vous avez 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, les uns à côté des autres, et d’appeler différentes méthodes des objets (bien sûr, casting) .
Lorsque vous êtes dans 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 avez besoin d'y injecter des éléments de l'extérieur, alors instanceof ou ses équivalents (isXXX()
, getType()
, ...) peuvent avoir des utilisations.
La "règle" générale consisterait à l'éviter autant que possible, en particulier lorsque vous contrôlez la hiérarchie des types et que vous pouvez utiliser le polymorphisme de sous-type, par exemple. L'idée n'est pas de demander à l'objet de quel type il s'agit et de faire quelque chose avec, mais plutôt de lui demander directement ou indirectement via un visiteur (essentiellement un double polymorphisme) d'effectuer une action.
Je conviens que ça peut avoir une mauvaise odeur. Beaucoup de cas, surtout dans un enchaîné si bloc, sent mauvais.
Parfois, il peut se comporter de manière inattendue ... Quelque chose que je suis arrivé une fois:
Class B extends A
Class C extends A
B b = new B();
C c = new C();
b instanceof B -> true
b instanceof C -> true
c instanceof C -> true
c instanceof B -> true
(Dans mon cas, cela est dû à la mise en veille prolongée de la création d'objets proxy .... mais juste dans le cas où le code dépendant de l'instance de est risqué)
Il peut très bien être utilisé comme contrôle de cohérence avant la coulée. en plus de vérifier que votre objet est de type correct, 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.
}
Qu'en est-il dans le cas d'une fabrique de création?.
public static Cage createCage(Animal animal) {
if (animal instanceof Dog)
return new DogHouse();
else if (animal instanceof Lion)
return new SteelCage();
else if (animal instanceof Chicken)
return new ChickenWiredCage();
else if (animal instanceof AlienPreditor)
return new ForceFieldCage();
...
else
return new GenericCage();
}