2010-01-16 11 views
8

De acuerdo, tengo la sensación de que ustedes podrán señalar rápidamente por qué estoy tan confundido acerca de esto, pero tengo una pregunta sobre por qué lo siguiente NO da como resultado un compilador error o advertencia:Objective-C Type Inference

NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ]; 

selectedObject es un NSObject y name pasa a ser el nombre de un tipo de @propertyint.

Lo que me deja perplejo es por eso que el compilador está perfectamente dispuesto a asumir que el resultado retorno de [ self.selectedObject valueForKey:name ] es de tipo NSNumber * (sin typecasting ella) con el fin de la cadena del mensaje con una llamada a integerValue.

Obviamente, KVC envuelve no-objeto tipos "número" en NSNumber, pero no hay manera para que el compilador sepa que -valueForKey: devolverá un NSNumber * en este caso particular.

¿Por qué esto no da como resultado una advertencia de compilación en la línea de "id puede que no responda a '-integerValue'"?

Respuesta

10

Espero haberlo hecho bien: Esto es porque id es "especial". A los objetos del tipo id se les puede enviar cualquier mensaje que desee, el compilador no realiza ninguna comprobación y todo se comprobará en el tiempo de ejecución. O, en otras palabras, el tipo id es la parte de "tipado dinámico" de Objective-C, mientras que todos los otros tipos (como NSObject) son la parte "tipado estático".

De esta forma puede elegir dónde desea usar el tipado estático y dónde desea usar el tipado dinámico. Es perfectamente legal para hacer algo como esto:

id str1 = @"Hello"; 
id str2 = [str1 stringByAppendingString:@", world"]; 

Pero por lo general se escriben las cadenas “fuerza” como NSString s, debido a que obtiene la conveniencia de verificación estática de tipos en tiempo de compilación, y sólo recurrir a tipado dinámico, donde el estático se pondría en el camino, como en la situación valueForKey.

+0

Gracias! Tenía la sensación de que tenía que ver con 'id' ser un tipo privilegiado en Objective-C. :) Mi tendencia es SIEMPRE apretar las cosas cuando sea posible, así que supongo que nunca me encontré con este comportamiento aparentemente extraño. Adivina que eso hace que 'id' sea poderoso y peligroso. Me pregunto si es mejor encasillar para darle al compilador un cierto contexto cuando se trata de 'id', o si está perfectamente bien dejarlo así si estás seguro de lo que' id' se convertirá (como fue el caso en mi ejemplo) . – LucasTizma

+0

La regla del pulgar es: "Escritura estática siempre que sea posible, escritura dinámica cuando sea necesario." (Puede buscar esa información en Google). En este caso, no me gustaría encasillar, solo haría la expresión más difícil de leer. Algunas veces tiene que encasillar para ayudar al compilador a elegir el método correcto - vea http://stackoverflow.com/questions/1113270. – zoul

+0

Gracias por el enlace. Me he encontrado con algunos pequeños errores desagradables como resultado de la denominación del método que pasa a "entrar en conflicto" con nombres de métodos SDK existentes. Pensé que el compilador se estaba volviendo loco conmigo. :) Y sí, soy totalmente partidario de la filosofía "Escritura estática en donde sea posible, mecanografía dinámica cuando sea necesario". Ahora, si solo Objective-C agregaría soporte para las colecciones escritas a máquina ... Al parecer, la mayoría de las veces, sé lo que van a almacenar mis colecciones. – LucasTizma

Cuestiones relacionadas