2010-06-01 10 views
24

Desde que empecé a Java que ha sido muy agravante para mí que no soporta conversiones implícitas de tipos numéricos a los booleanos, por lo que no puede hacer cosas como:¿Por qué Java y C# no tienen conversiones implícitas a boolean?

if (flags & 0x80) { ... } 

vez que tiene que pasar por esta locura :

if ((flags & 0x80) != 0) { ... } 

Pasa lo mismo con null y objetos. Todos los demás lenguajes tipo C que conozco, incluido JavaScript, lo permiten, así que pensé que Java era simplemente idiota, pero acabo de descubrir que C# es el mismo (al menos para los números, no sé sobre null/objects): http://msdn.microsoft.com/en-us/library/c8f5xwh7(VS.71).aspx

Microsoft lo cambió a propósito desde C++, entonces ¿por qué? Claramente me falta algo. ¿Por qué cambiar (lo que pensé que era) lo más natural del mundo para que sea más largo escribir? ¿Qué demonios está mal con eso?

+21

No es una locura, simplemente no es lo que está acostumbrado. – ColinD

+53

'si (estado = CODE_RED) launch_nuclear_missiles();' –

+24

la verdadera pregunta es, ¿por qué lenguajes como C permiten la locura de conversión implícita a Boolean :) – Oak

Respuesta

30

Tanto Java como C# abandonaron las conversiones implícitas a los booleanos para reducir la posibilidad de error del programador.

Por ejemplo, muchos programadores accidentalmente escribirían:

if(x = 5) { ... } 

en lugar de:

if(x == 5) { ... } 

¿Cuál de los resultados del curso en el comportamiento completamente diferente, ya que la primera instrucción realiza una asignación (que siempre resultado en verdadero), mientras que el segundo realiza una comparación. En el pasado, los desarrolladores a veces se escriben tales asignaciones en sentido inverso para evitar el peligro, ya que:

if(5 = x) { ... } // doesn't compile. 

Ahora, en C#, todavía puede crear operadores de conversión implícitas a bool para sus propios tipos - a pesar de que rara vez es aconsejable , ya que la mayoría de los desarrolladores no lo esperan:

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 
37

Para mayor claridad. Esto hace que el siguiente error simplemente ilegal:

int x = ...; 

if (x = 0) // in C: assign 0 to x and always evaluate to false 
    ....  // never executed 

Nota: los compiladores más modernos C/C++ mostrará una advertencia (pero no un error) en este modelo sencillo, pero hay muchas variaciones posibles. Puede arrastrarse sobre ti.

+0

En teoría, en C# es posible que el tipo de 'x' implemente operadores de conversión implícitos de' int' y 'bool', en cuyo caso se compilaría en C#. Si calificas que 'x' es un tipo numérico integrado (como' int'), entonces tu ejemplo es absolutamente correcto. – LBushkin

+2

@LBushkin, tienes razón, lo agregaré. Pero suponiendo que una conversión personalizada es un poco exagerada aquí. –

+1

Muchas de las presentaciones de Underhanded C presentan esta pequeña castaña escondida en algún lugar del código. – Jason

10

Tal vez sintieron que ser más explícito estaba más en línea con un lenguaje fuertemente tipado.

+2

Esto parece más un comentario que una respuesta – Supuhstar

3

Incluso los programadores más experimentados tienen problemas con una conversión implícita a booleano. Por mi parte, aprecio esta pequeña característica.

6

La conversión implícita de cualquier valor int (como (flags & 0x80)) a un valor booleano implica un mapeo definido por el idioma desde un valor int a un valor booleano. C hizo esto y causó una gran cantidad de confusión y un gran error del programador. No hay una buena razón por la cual un valor int nulo SIEMPRE sea verdadero (o falso) y una gran cantidad de buenas razones por las que desee dejar la decisión al programador. Por estas razones, la mayoría de los lenguajes modernos han abandonado la conversión implícita a boolean.

Si escribe siete caracteres adicionales cada vez que hace una prueba de bit constituye 'locura', es posible que esté en la profesión equivocada.Si realiza pruebas de bits en un int con mucha frecuencia, es posible que desee pensar si está optimizando prematuramente para ahorrar memoria.

+1

Tal "locura" es la razón por la cual tenemos el operador '++', que solía optimizar las instrucciones INCR, pero ahora solo sirve como un atajo de escritura. –

+0

Estoy de acuerdo. Las conversiones implícitas a booleanos pueden ser útiles, pero declarar que algunos valores arbitrarios son falsos y que otros valores igualmente arbitrarios son ciertos no es el camino. En Ruby y muchos Lisp, por ejemplo, * todo * es verdadero, excepto 'false' y' nil'. Esa es una regla * simple * y obvia. "Algunos números son verdaderos y algunos son falsos, a menos que escriba su propio tipo de número, en cuyo caso no son ni verdaderos ni falsos" no es exactamente una regla simple. Además, ¿por qué los números deben ser verdaderos o falsos pero no, digamos, matrices? O '¿Usuario? –

2

Algunos lenguajes de programación no tienen coerción automática. Un entero, por ejemplo, solo se puede comparar con otro entero; la asignación a una variable no entera da como resultado un error. Tal es el sello distintivo de un lenguaje fuertemente tipado.

que Java hace ningún tipo de coacción es una comodidad para usted y rompe el modelo fuerte tipificación.

El mapeo de todo el rango de enteros, o la gama aún mayor de flotantes, en los dos valores booleanos está plagado de desacuerdos sobre la asignación arbitraria de "veracidad" y "falsedad".

  • ¿Qué valores se convierten en falsos y verdaderos? Si eres C, solo se asigna a cero los falsos y todos los demás valores son verdaderos. Si eres el shell bash, está invertido.
  • ¿Cómo deben correlacionarse los valores negativos?

Cuando intenta convertir automáticamente un doble a un entero, Java indica esto como un error de "pérdida de precisión". Por analogía, convertir un número en booleano también debería dar como resultado una pérdida de precisión. En cambio, Java eligió no admitirlo sintácticamente.

+0

No conozco ningún debate sobre cómo mapear 'int' a' bool'. ¿Podrías proporcionar un enlace? –

+0

No hay debate oficial, per se. Pero dado que algunos idiomas tienen diferentes ideas de cómo hacer la conversión, claramente no hay un estándar. –

+0

Bueno, hay un estándar es su X86 y la ALU. Verdadero se evalúa como cero cero y falso cero. Simple ALU 'y' conjunto de instrucciones. No hay un estándar por decir, porque es fundamental cómo funcionan las computadoras modernas. – Chad

8

Lo tienes al revés.
En realidad, C no admite boolean, por lo que if (y cualquier otra instrucción condicional) realmente espera un valor de int, no boolean. Entonces el valor int de 0 se trata como falso y cualquier otro valor se trata como true.

Algunas personas realmente encontrar un poco ambigua, ya que este tipo de comportamiento puede dar lugar a muchos errores, como otros han señalado. Debido a esto, los diseñadores de Java han optado por admitir solo los tipos boolean en las declaraciones de condición. Y cuando Microsoft decidió implementar MS-Java (AKA C#), tomaron prestado este diseño principal.

Si no le gusta, se puede programar en una variedad de idiomas que no tienen esta restricción.

+1

+1 para MS-Java (AKA C#) – whiskeysierra

Cuestiones relacionadas