tutorial objective example objective-c

objective c - objective - ¿Cuál es la diferencia entre declarar una variable "id" y "NSObject*"?



objective c vs swift (4)

Con una id tipo variable, puede enviar cualquier mensaje conocido y el compilador no se quejará. Con un NSObject * tipo variable, solo puede enviar mensajes declarados por NSObject (no métodos de ninguna subclase) o bien generará una advertencia. En general, id es lo que quieres.

Explicación adicional: Todos los objetos son esencialmente de tipo id . El objetivo de declarar un tipo estático es decirle al compilador: "Asuma 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á: "OK, no tengo suficiente información aquí. Estoy escogiendo una firma de método al azar". (Esto generalmente no será ayudado por la declaración de NSObject* , sin embargo. Por lo general, el conflicto es entre dos clases más específicas.)

En Objective-C, ¿cuál es la diferencia entre declarar un id variable frente a declararlo NSObject * ?


Desde mi comprensión limitada de Objective-C, no todos los objetos se derivan de NSObject (a diferencia de 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.


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, declara un delegado y probará todos los envíos de métodos con respondsToSelector: llamadas, puede usar una id .

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


Me gustaría agregar otra diferencia. Cuando agrega un protocolo a la id , ya no significa que será de tipo NSObject * , simplemente significa que será cualquier clase que confirme a ese protocolo.

Entonces, por ejemplo, este código no arrojará ningún error, ya que la categoría NSDelayedPerforming tiene ese método:

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

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

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