Подтвердить что ты не робот

Причина для приоритета instanceof/

В обоих С#/Java приоритет оператора is соответственно instanceof приводит к некоторым уродливым необходимым скобкам. Например, вместо записи if (!bar instanceof Foo) вам нужно написать if (!(bar instanceof Foo)).

Итак, почему языковые команды решили, что ! имеет более высокий приоритет оператора, чем /instanceof? По общему признанию, в С# вы можете перезаписать operator!, что приведет к другому результату в некоторых ситуациях, но эти ситуации кажутся чрезвычайно редкими (и неинтуитивными в любом случае), в то время как случай проверки того, что что-то не является типом или подтипом что-то гораздо более вероятно.

4b9b3361

Ответ 1

Теория заговора:

Дизайнеры С# не хотят, чтобы вы использовали оператор is. Использование этого оператора часто является запахом плохого дизайна ООП. Если вы часто используете его часто, это, вероятно, означает, что иерархия классов неверна, и вам нужно больше полагаться на виртуальные методы и шаблоны. Дизайнеры Java пошли еще дальше: они назвали оператор instanceof, чтобы вы съедали каждый раз, когда используете его.

На самом деле это маловероятно. Существует много случаев, когда разработчики языка и библиотеки делают некоторые функции неудобными в использовании. Некоторые примеры: кодировки символов в .NET(вы всегда должны использовать Unicode), goto в Pascal (вы должны его избегать) и т.д. Иногда это вызвано плохим дизайном (например, WPF в .NET), но иногда он преднамеренным.

Ответ 2

В Java instanceof является одним из реляционных операторов и имеет тот же приоритет, что и другие:

RelationalExpression:
    ShiftExpression
    RelationalExpression < ShiftExpression
    RelationalExpression > ShiftExpression
    RelationalExpression <= ShiftExpression
    RelationalExpression >= ShiftExpression
    RelationalExpression instanceof ReferenceType

С этой точки зрения имеет смысл, что эти две строки должны следовать одной и той же структуре:

if (!(a instanceof b))
if (!(a < b))

Ответ 3

Вот мои мысли по этому вопросу без авторитетного источника.

instanceof - очень большой оператор. Большинство операторов не более двух символов. Кроме того, instanceof должно иметь пробелы между ним и переменной. Из-за этих двух уникальных вещей, когда вы смотрите на выражение типа !bar instanceof Foo, instanceof, естественно, разделяет !bar и Foo, и многие люди посчитают удивительным, если !bar выражение.

Подобные линии мыслей также могут применяться к is, с дополнительным аргументом только того, что уже сделала Java.

Ответ 4

Я думаю, что это просто исторический. Если я правильно помню в первых версиях Java, вы даже не могли писать if(a instanceof Foo || a instanceof Bar) без круглых скобок. Я думаю, что произошли изменения вокруг Java 2. Я не знаю, почему они не поставили его на более высокий приоритет (например, выше, чем логический). Может быть, потому, что это будет мешать оператору typecast и, таким образом, нарушить совместимость тогда?

С#, похоже, только что использовал тот же приоритет, что и Java.

Я по-прежнему считаю, что это также ошибка, чтобы сохранить приоритет побитового и/или на том же уровне, что и логический и/или. Мне нужно писать такие вещи, как if( (x&(FLAG1|FLAG2)) != 0) ….

Ответ 5

Потому что, написав if (!bar instanceof Foo), он отменяет строку, а затем ищет instanceof. потому что это самый левый оператор, и я не думаю, что экземпляр даже имеет приоритет

то if (!(bar instanceof Foo)) он делает его instanceof первым, а затем отрицает все это.

если вам нужно отменить бар, а затем проверить экземпляр, тогда выполните ((!bar) instanceof Foo)

Ответ 6

  • instanceof - очень длинное слово по сравнению с базовыми операторами типа + или ++. Когда вы читаете условие, вы просто потеряли фокус, по крайней мере, я это делаю.
  • Он окружен пробелами, которые могут повысить читаемость, но, с другой стороны, вы не можете подключить его к другим операндам, например. подобный 5+6 может сделать.

Я считаю, что ребята решили сказать: ok, более низкий приоритет, поэтому каждый должен предоставить скобки, чтобы быть уверенным, что происходит

Ответ 7

Честно говоря, выражение типа !b instanceof SomeType (read: "negate b, а затем проверить, имеет ли результирующее значение тип SomeType" ), не имеет особого смысла в Java:

Логически, b должен был быть каким-то булевым объектом (так что ! работает), и даже если вы отрицаете его значение, оно все равно будет логическим значением того же типа, что и раньше, поэтому зачем беспокоиться отрицая это в первую очередь?

(На самом деле вы даже не можете этого сделать: b не может быть boolean, потому что instanceof требует, чтобы он был реальным Object, но опять же, если b является boolean, !b все равно будет оцениваться примитивным boolean, поэтому instanceof не работает.)

Поэтому мы можем сказать, что !b instanceof SomeType вообще не имеет смыслового значения в Java. Поэтому мы могли бы переназначить его значение, чтобы "проверить, не имеет ли b типа SomeType" - не можем ли мы?

Учитывая, что это могло быть изменено семантически и все еще не было сделано, я оставляю за собой заключение, что это не было действительно преднамеренным, но была более прагматичная причина пойти с более низким приоритетом для instanceof:

В верхней части моей головы я подозреваю, что синтаксический анализ усложняется, если вы дадите instanceof более высокий приоритет, чем унарный оператор !. Вы можете проверить это.

С другой стороны, если !b instanceof SomeType означало бы "проверить, не имеет ли b типа SomeType", это все равно может заставить начинающих программистов думать, что ! работает на b, когда на самом деле это отрицает результат instanceof, поэтому он менее двусмыслен, чтобы оставить !b instanceof SomeType существенно undefined.

Ответ 8

instanceof является двоичным оператором. ! является унарным оператором.

Было бы очень сложно использовать instanceof для соединения более жестко, чем !.
Классическим примером путаницы является ** и - в Python, где мы имеем:

-1 ** 2 == -(1 ** 2)  # true

Я не знаю о вас, но это просто смешно для меня в Python, поэтому я рад, что они не делают то же самое на Java.

Другой пример Python:

False is (not None)   # false

и

False is not None     # true

который, как мне кажется, в равной степени запутан, на этот раз, потому что is и is not - разные операторы.

Ответ 9

Потому что язык программирования C получил это неправильно, а Java слепо следовать C.

В C,! и ~ имеют одинаковый приоритет. На практике это фактически не имеет большого значения, поскольку пишет   < б скорее, чем   ! (А >= б).

Но нет никакого оператора.

Вы также можете спросить, почему /*/* */*/не гнездо правильно. Или почему Java рассчитывает от 0. Или почему должно быть ключевое слово void. Или почему Java использует ужасную {{} {}} нотацию вместо endif (или fi). Это все наследие C.

И, возможно, не зря. C программисты будут утверждать, что все эти вещи являются правильным подходом, потому что это то, к чему они привыкли. И первая работа Java должна была стать замеченной и использоваться, в отличие от многих других давно забытых языков программирования.

Будьте благодарны, что Java не имеет нулевых завершенных строк.