2009-01-21 16 views

Respuesta

51

Con una variable escrita a id, puede enviarle cualquier mensaje conocido y el compilador no se quejará. Con una variable tipeada NSObject *, solo puede enviar mensajes declarados por NSObject (no métodos de cualquier subclase) o de lo contrario generará una advertencia. En general, id es lo que quiere.

Explicación adicional: Todos los objetos son esencialmente del tipo id. El objetivo de declarar un tipo estático es decirle al compilador: "Supongamos que este objeto es miembro de esta clase". Entonces, si le envía un mensaje que la clase no declara, el compilador puede decirle, "¡Espera, ese objeto no debe recibir ese mensaje!" Además, si dos clases tienen métodos con el mismo nombre pero diferentes firmas (es decir, argumentos o tipos de devolución), puede adivinar a qué método se refiere la clase que ha declarado para la variable. Si se declara como id, el compilador levantará las manos y le dirá: "Está bien, no tengo suficiente información aquí. Estoy escogiendo una firma de método al azar". (Esto generalmente no se verá favorecido por la que se declara NSObject*, sin embargo. Por lo general, el conflicto es entre dos clases más específicas.)

+2

Gran explicación, aunque dudo en decir que "en general, id es lo que quieres". Aunque "id" es bastante flexible debido a la tipificación dinámica, también prácticamente no ofrece advertencias, por lo que si llama a un método no compatible, lo que podría capturarse en tiempo de compilación se convierte en un problema de tiempo de ejecución. Tipado estático (con MyClassName * etc.) cuando se usa con prudencia puede simplificar mucho la vida, especialmente al depurar en Xcode (puede mostrar un resumen más inteligente del objeto) o capturar llamadas a métodos con selectores mal escritos o incompletos. –

+0

La distinción que quise dibujar es específicamente entre id y NSObject *, no tipificación estática en general. Es mucho más común que desee utilizar id que estéticamente escriba como NSObject. – Chuck

+0

@simpleBob: De ahí "cualquier mensaje conocido". – Chuck

17

id significa "un objeto", NSObject * significa "una instancia de NSObject o una de sus subclases". Hay objetos en Objective-C que no son NSObject s (los que encontrarás en Cocoa en este momento son NSProxy, Protocol y Class). Si algún código espera un objeto de una clase en particular, declarar que ayuda al compilador a verificar que lo está utilizando correctamente. Si realmente puede tomar "cualquier objeto", por ejemplo, está declarando un delegado y probará todos los envíos de métodos con llamadas respondsToSelector:, puede usar un id.

Otra manera de declarar una variable de objeto es como "id <NSObject>", que significa "cualquier objeto que implementa el NSObject protocolo.

+0

NSProxy y el protocolo son clases. "Clase" no es una clase, sino simplemente un tipo que puede referirse a punteros a objetos de clase. No los agrupe juntos – user102008

+0

@ user102008: puede enviar mensajes a una clase, lo que lo convierte en un objeto en el mundo de objc. –

+0

sí, los objetos de clase son objetos, pero no son de una clase llamada "Clase" – user102008

10

Desde mi limitada comprensión de Objective-C, no todos los objetos se derivan de NSObject (a diferencia Java donde todos los objetos se derivan de Object). Teóricamente puede tener otros objetos raíz. Id podría aplicarse a cualquiera de esos objetos derivados no-NSObject.

0

Me gustaría agregar otra diferencia. Cuando agrega un protocolo a id, ya no significa que será del tipo NSObject *, solo significa que será cualquier clas s que confirma a ese protocolo.

Así, por ejemplo, este código no arrojar ningún error, ya que NSObject 's categoría NSDelayedPerforming tiene ese método:

id testId; 
[testId performSelector:@selector(isKindOfClass:) withObject:[NSObject class] afterDelay:.5]; 

Sin embargo, este código se mostrará el error No known instance method for selector "performSelector:withObject:afterDelay:":

id<NSMutableCopying> testId; 
[testId performSelector:@selector(isKindOfClass:) withObject:[NSObject class] afterDelay:.5]; 
Cuestiones relacionadas