Я предпочитаю использовать локальные переменные, а не множественные вызовы того же метода.
/*
* I prefer this
*/
Vehicle vehicle = person.getVehicle()
if (vehicle instanceof Car) {
Car car = (Car) vehicle;
car.openSunroof();
} else if (vehicle instanceof Bike) {
Bike bike = (Bike) vehicle;
bike.foldKickstand();
}
/*
* Rather than this
*/
if (person.getVehicle() instanceof Car) {
Car car = (Car) person.getVehicle();
car.openSunroof();
} else if (person.getVehicle() instanceof Bike) {
Bike bike = (Bike) person.getVehicle();
bike.foldKickstand();
}
Который Вы предпочитаете и почему?
Да, первый определенно лучше. Я бы никогда не выбрал второй метод.
Но вам следует больше подумать об использовании полиморфизма. Так сильно полагаться на instanceof
- это не очень хороший объектно-ориентированный дизайн.
Я предпочитаю первую версию по всем указанным вами причинам. В частности (просто для того, чтобы прояснить ваш четвертый пункт), это означает, что вы определенно получите последовательные результаты... вы можете получить ужасно неприятные результаты со второй версией, если getVehicle()
вернет Car
при первом вызове, затем Bike
при втором....
Сторона производительности меня не беспокоит (например, я с удовольствием позвоню List.size()
несколько раз), но читабельность, последовательность и неповторяемость - все это гораздо важнее. По сути, первый фрагмент передает идею "получить значение, а затем использовать его" намного эффективнее, чем второй.
Так что да, я с вами... кто-нибудь рекомендует вам вторую форму?
Обычно мне не нравится введение дополнительных переменных, поскольку каждый бит добавленного состояния делает метод более сложным. Но даже я бы сказал, что в вашем примере это оправдано, поскольку переменная заменяет 4 повторения идентичного кода.
Но переменная обязательно должна быть final
!
Согласен, но и на уровне проектирования классов я стараюсь сократить использование 'instanceof'.
Я лично считаю, что первый чище. Однако при условии, что вызываемый метод не требует больших вычислений, это не имеет большого значения.
Вероятно, второй вариант немного быстрее (если вы используете Java 1.6), потому что в первом примере вы делаете копию переменной, а виртуальная машина Java, скорее всего, встроит вызов функции в обоих примерах. Конечно, оптимизация никогда не является аргументом в пользу подобных вызовов. Компилятор выполняет столько оптимизаций, что нам не о чем беспокоиться (часто он просто снижает скорость, потому что мы недостаточно хорошо это знаем).
Как и все, кто до сих пор отвечал на этот вопрос, я определенно предпочитаю первый стиль. Хотя это может быть еще чище:
Vehicle vehicle = person.getVehicle()
if (vehicle instanceof Car) {
((Car) vehicle).openSunroof();
} else if (vehicle instanceof Bike) {
((Bike) vehicle).foldKickstand();
}
Оба примера нуждаются в доработке. Попробуйте перенести поведение в абстрактный (или защищенный) метод на Vehicle. Если это код, который вы не можете изменить, используйте композицию, чтобы поместить его в интерфейс в вашей кодовой базе, чтобы не загрязнять остальной код плохим дизайном библиотеки, которую вы используете. Это определенно запах кода. См. статью "Замените условность полиморфизмом" в книге Фаулера "Рефакторинг".