За эти годы я старался избегать instanceof
когда это возможно. Используя полиморфизм или шаблон "посетитель" когда это применимо. Я предполагаю, что это просто упрощает обслуживание в некоторых ситуациях... Есть ли какие-либо другие недостатки, о которых нужно знать?
Я действительно однако вижу его тут и там в библиотеках Java, таким образом, я предполагаю, что это имеет свое место? При каких обстоятельствах это предпочтительно? Это когда-либо неизбежно?
Я могу представить себе некоторые случаи, например, у вас есть некоторые объекты библиотеки, которые вы не можете расширить (или это было бы неудобно), возможно, смешанные с некоторыми вашими объектами, все с одним и тем же базовым классом, вместе в коллекции.
Я полагаю, что в таком случае может оказаться полезным использование instanceof для различения обработки этих объектов.
То же самое в части поддержки устаревшего кода, когда вы не можете внедрить какое-то новое поведение во множество старых классов только для того, чтобы добавить новую небольшую функцию или исправление ошибки ...
Его вполне можно использовать как проверку работоспособности перед применением; помимо проверки того, что ваш объект имеет правильный тип, он также проверяет, не является ли он нулевым.
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.
}
Это определенно имеет место в стандартной реализации равно
. Например.
public boolean equals ( Object o )
{
if ( this == o )
{
return true;
}
if ( ! (o instanceof MyClass) )
{
return false;
}
// Compare fields
...
}
Что важно знать о instanceof, так это то, что его LHS может иметь значение null
, и в этом случае выражение оценивается как false
.
Я согласен, что это может иметь плохой запах. Много instanceof, особенно в цепочке if блока, дурно пахнет.
Иногда он может вести себя так, как вы не ожидаете... Однажды у меня случилось следующее:
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
(в моем случае это произошло из-за того, что hibernate сделал прокси-объекты...., но это просто случай, когда код, зависящий от instanceof, рискован)
Когда вы находитесь внутри чисто объектно-ориентированной модели, тогда instanceof
определенно является запахом кода.
Если, однако, вы не используете 100% объектно-ориентированную модель или вам нужно внедрить в нее что-то извне, тогда instanceof или его эквиваленты ( isXXX ()
, getType ()
, ...) может иметь свое применение.
Общее «правило» - избегать этого, когда это возможно, особенно когда вы управляете иерархией типов и можете использовать, например, полиморфизм подтипов. Идея состоит не в том, чтобы спросить объект, что это за тип и что-то с ним сделать, а в том, чтобы прямо или косвенно попросить объект через посетителя (по сути, двойной полиморфизм) выполнить какое-либо действие.
Я думаю, что когда вам абсолютно необходимо знать тип объекта, instanceof
является лучшим вариантом.
Плохой практикой было бы иметь много instanceof
ов, один рядом с другим, и в соответствии с ними вызывать различные методы объектов (конечно, с кастингом).
Это, вероятно, отразит, что иерархия нуждается в переосмыслении и, возможно, в рефакторинге.