(Пожалуйста, не советуйте мне еще абстрагировать X
и добавить к нему еще один метод.)
В C ++, когда у меня есть переменная x
из введите X *
, и я хочу сделать что-то конкретное, если оно также относится к типу Y *
( Y
является подклассом X
) , Я пишу это:
if(Y* y = dynamic_cast(x)) {
// now do sth with y
}
То же самое кажется невозможным в Java (или это так?).
Вместо этого я прочитал этот код Java:
if(x instanceof Y) {
Y y = (Y) x;
// ...
}
Иногда, когда вы не t имеет переменную x
, но вместо этого это более сложное выражение, именно из-за этой проблемы вам нужна фиктивная переменная в Java:
X x = something();
if(x instanceof Y) {
Y y = (Y) x;
// ...
}
// x not needed here anymore
(Обычное дело, что something ()
- это iterator.next ()
. И здесь вы видите, что вы также не можете вызвать это дважды. Вам действительно нужна фиктивная переменная.)
Вам действительно не нужно x
здесь вообще - он у вас просто потому, что вы не можете выполнить проверку instanceof
сразу с приведением. Сравните это снова с довольно распространенным кодом C ++:
if(Y* y = dynamic_cast( something() )) {
// ...
}
Из-за этого я ввел функцию castOrNull
, которая позволяет избежать фиктивной переменной x
. Теперь я могу написать следующее:
Y y = castOrNull( something(), Y.class );
if(y != null) {
// ...
}
Реализация castOrNull
:
public static T castOrNull(Object obj, Class clazz) {
try {
return clazz.cast(obj);
} catch (ClassCastException exc) {
return null;
}
}
Теперь, Мне сказали, что использование этой функции castOrNull
таким образом - зло для . Это почему? (Или, чтобы задать более общий вопрос: согласны ли вы и также считаете, что это зло? Если да, то почему? Или вы думаете, что это допустимый (может быть, редкий) вариант использования?)
Как уже было сказано, я не « Я не хочу обсуждать, является ли использование такого понижающего преобразования хорошей идеей. Но позвольте мне вкратце пояснить, почему я иногда его использую:
Иногда я попадаю в ситуацию, когда мне приходится выбирать между добавлением еще одного нового метода для очень конкретной вещи (который будет применяться только для одного отдельного подкласса в одном конкретном случае) или используя такой instanceof
check. По сути, у меня есть выбор между добавлением функции doSomethingVeryVerySpecificIfIAmY ()
или выполнением проверки instanceof
. И в таких случаях Я считаю, что последний более чистый.
Иногда у меня есть коллекция некоторого интерфейса / базового класса, и для всех записей типа Y
я хочу что-то сделать, а затем удалить их из коллекции. (Например, у меня был случай, когда у меня была древовидная структура, и я хотел удалить все дочерние элементы, которые являются пустыми листьями.)