Почему Java и С# не имеют неявных преобразований в boolean?
С тех пор как я начал Java, для меня было очень усугублено то, что он не поддерживает неявные преобразования из числовых типов в booleans, поэтому вы не можете делать такие вещи, как:
if (flags & 0x80) { ... }
вместо этого вы должны пройти через это безумие:
if ((flags & 0x80) != 0) { ... }
То же самое с нулем и объектами. Каждый другой C-подобный язык, который я знаю, включая JavaScript, позволяет это, поэтому я думал, что Java просто глупо, но я только что обнаружил, что С# тот же (по крайней мере, для чисел, не знаю о null/objects):
http://msdn.microsoft.com/en-us/library/c8f5xwh7(VS.71).aspx
Microsoft специально изменила его с С++, так почему? Ясно, что я что-то пропускаю. Почему изменилось (что я думал) самое естественное в мире, чтобы сделать его более длинным для ввода? Что на Земле не так?
Ответы
Ответ 1
Для ясности. Это делает следующую ошибку просто незаконной:
int x = ...;
if (x = 0) // in C: assign 0 to x and always evaluate to false
.... // never executed
Примечание. Большинство современных компиляторов C/С++ предоставят предупреждение (но не ошибку) по этому прямолинейному шаблону, но есть много вариантов. Он может подкрасться к вам.
Ответ 2
Как Java, так и С# отказались от неявных преобразований в booleans , чтобы уменьшить вероятность ошибки программиста.
Например, многие программисты случайно напишут:
if( x = 5 ) { ... }
вместо:
if( x == 5 ) { ... }
Что, конечно, приводит к совершенно другому поведению, поскольку первый оператор выполняет присваивание (которое всегда будет иметь значение true), а второе выполняет сравнение. Раньше разработчики иногда записывали такие задания в обратном порядке, чтобы избежать ловушки, поскольку:
if( 5 = x ) { ... } // doesn't compile.
Теперь, в С#, вы все равно можете создавать неявные операторы преобразования в bool
для ваших собственных типов - хотя это редко бывает целесообразным, так как большинство разработчиков этого не ожидают:
public class MyValue
{
public int Value { get; set; }
public static implicit operator bool( MyValue mb )
{
return mb.Value != 0;
}
}
MyValue x = new MyValue() { Value = 10; }
if( x ) { ... } // perfectly legal, compiler applies implicit conversion
Ответ 3
Возможно, они чувствовали, что более явное больше соответствует строго типизированному языку.
Ответ 4
У вас есть это назад.
Это фактически C, который не поддерживает boolean
, поэтому if
(и любой другой условный оператор) фактически ожидает значение int
, а не boolean
. Тогда значение int 0
рассматривается как ложное, а любое другое значение рассматривается как true
.
Некоторые люди на самом деле находят это немного неоднозначным, потому что этот тип поведения может привести к многочисленным ошибкам, как указывали другие. Из-за этого разработчики Java отказались поддерживать только теги boolean
в операторах условий. И когда Microsoft решила внедрить MS-Java (AKA С#), они заимствовали этот проект.
Если вам это не нравится, вы можете программировать на разных языках, которые не имеют этого ограничения.
Ответ 5
Неявное преобразование любого значения int (например, (flags и 0x80)) в boolean подразумевает языковое заданное сопоставление от значения int к логическому. C сделал это и вызвал огромное количество путаницы и много ошибок программиста. Нет никакой веской причины, по которой значение null int всегда означает true (или false) и множество веских причин, по которым вы, возможно, захотите оставить решение программисту. По этим причинам неявное преобразование в boolean было отменено большинством современных языков.
Если вводить семь дополнительных символов каждый раз, когда вы выполняете бит тест, это "безумие", вы можете быть не в той профессии. Если вы часто выполняете бит-тесты в int, вы можете подумать о том, что вы преждевременно оптимизируете сохранение памяти.
Ответ 6
Даже у самых опытных программистов есть проблемы с неявным преобразованием в boolean. Я для одного ценю эту небольшую особенность.
Ответ 7
В некоторых языках программирования нет автоматического принуждения. Например, целое число можно сравнить только с другим целым числом; Присвоение не целочисленной переменной приводит к ошибке. Таков признак строго типизированного языка.
То, что Java делает любое принуждение, является для вас удобством и разбивает модель сильной печати.
Отображение всего диапазона целых чисел - или даже большего диапазона поплавков - на два булевых значения чревато разногласиями по поводу произвольного присвоения "истины" и "фальшивости".
- Какие значения отображаются на false и true? Если вы C, только нулевые карты равны false, а все остальные значения - true. Если вы являетесь оболочкой bash, она отменяется.
- Как отображать отрицательные значения?
Когда вы пытаетесь автоматически преобразовать double в целое число, Java обозначает это как ошибку "потери точности". По аналогии, преобразование числа в логическое значение также должно приводить к потере точности. Вместо этого Java предпочла не синтаксически поддерживать его.