40

I know that when we want to create an unknown value object we use id. However, I'm curious that why did Apple to choose id which decides it's value during runtime, when every object is a subclass of NSObject. So instead of id delegate we could have used NSObject *delegate Does anyone know why? Thanks.

justin
  • 104,054
  • 14
  • 179
  • 226
TheAmateurProgrammer
  • 9,252
  • 8
  • 52
  • 71

4 Answers4

41

id erases the type and it is equivalent to saying "this object responds to any selector visible to the translation". Of course, it is your responsibility to make sure your program is correct when you erase types (and also when you typecast them).

If the type were NSObject, then the compiler would say "NSObject may not respond to selector" if the selector was not declared in NSObject's interface or the protocols it adopts. In that event, you could also add a typecast to cast it to the type you expect.

With strict/correct types, the compiler can kick in and help you out, which is great because ObjC is a very dynamic language.

id is particularly useful when using (or building) collections types. Adding an object would not be a problem unless you defined a new root type (does not inherit from NSObject). Getting a value from the collection would require a typecast if we were to use it as something other than our base class (NSObject).

Objective-C does not support generics - you cannot, for example, declare an NSArray of NSStrings. You can populate an NSArray with NSStrings and pass this through id for a more natural written style when type safety is not preserved (a la generics).

So, let's expand on this with some real code.

Example A

NSString * string = [array objectAtIndex:0]; // << trust me (via id)
return [string length];
-or-
return [[array objectAtIndex:0] length]; // << trust me (via id)

Example B

And now let's say id is not available and we fix all our compiler warnings because it's the right thing to do:

NSString * string  = (NSString*)[array objectAtIndex:0]; // << typecast == trust me
return [string length];
-or-
return [(NSString*)[array objectAtIndex:0] length]; // << typecast == trust me

id doesn't decide its value at runtime, nor does any NSObject. ObjC objects don't perform implicit promotions, they just cast the pointer through without formal promotion.

Related to your example, I actually declare my delegates and parameters as NSObjects with protocols:

NSObject<MONShapeDelegate>* delegate;
Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
justin
  • 104,054
  • 14
  • 179
  • 226
  • It might differ in other compilers than the ones I used, but as far as I know, if you declare a type as NSObject, the compiler will assume the object implements all methods of SomeProtocol, even the optional ones. – Aberrant Oct 26 '11 at 14:25
  • @Aberrant if a delegate method is optional, it's up to the *caller* to verify the object responds to the selector. – justin Oct 26 '11 at 14:29
  • I know, that's why I said the compiler assumes they are implemented. If it didn't, optionals would always cause warnings, as the compiler cannot be sure if the objects will respond at runtime. – Aberrant Oct 26 '11 at 14:38
  • Ah, ok - I misunderstood your point the first time I read it. – justin Oct 26 '11 at 14:45
  • >> "this object responds to any selector visible to the translation" << What do you mean by "translation" in this context? – pkamb Oct 03 '16 at 22:40
12

every object is a subclass of NSObject

That is an incorrect statement. You can create objects that do not inherit from NSObject. it's not really recommended, but it is possible.

NSProxy is an example - it does not inherit from NSObject.

Jasarien
  • 58,279
  • 31
  • 157
  • 188
  • 3
    This is just a clone of my answer! – James Webster Oct 26 '11 at 14:49
  • 1
    Sorry :/ I wrote it when there were no answers, you beat me to the punch... no hard feelings and not really any need for a down vote... Also, you didn't mention `NSProxy`... – Jasarien Oct 26 '11 at 15:12
  • 1
    If it's a stack and this answer at the bottom then @Jasarien answered firstly ;) – beryllium Oct 26 '11 at 15:43
  • @beryllium I'm unsure of the answer order, but I'm sure I answered first. – James Webster Oct 26 '11 at 16:01
  • @JamesWebster answered first. I wrote my answer when there were no answers, however, I was too slow in submitting. Didn't know you had already answered until I posted mine. – Jasarien Oct 26 '11 at 16:13
  • 2
    @beryl: The default display order of answers is binned by vote total, then randomized within each tier. If you really want to know the exact post time, there's a tooltip attached to the "answered X hours ago" that will give you the timestamp. You can also hit the "oldest" tab at the top of the answers section to order the answers by posting date. – jscs Oct 26 '11 at 17:32
  • 1
    Maybe not worth mentioning almost seven years later, but: answering a question is not the right way to correct a factual error in the question. You should comment on the question or even rewrite it. – Isaac Rabinovitch Aug 01 '18 at 19:41
3
typedef struct objc_object {
    Class isa;
} *id;

Above is the actual definition of the id in Objective-C language. Objective-C runtime system is built around id and Class. Nothing have to do with NSObject or common super class.

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-SW3

The NSObject Class

NSObject is a root class, and so doesn’t have a superclass. It defines the basic framework for Objective-C objects and object interactions. It imparts to the classes and instances of classes that inherit from it the ability to behave as objects and cooperate with the runtime system.

A class that doesn’t need to inherit any special behavior from another class should nevertheless be made a subclass of the NSObject class. Instances of the class must at least have the ability to behave like Objective-C objects at runtime. Inheriting this ability from the NSObject class is much simpler and much more reliable than reinventing it in a new class definition.

I think, this is because it is originally C not C++ (or other more strict typing languages).

9dan
  • 4,222
  • 2
  • 29
  • 44
1

every object is a subclass of NSObject

That's not correct. You could make an object that extends from nothing as a root class.

That's perhaps why id was introduced.

James Webster
  • 31,873
  • 11
  • 70
  • 114