The id type is not an actual type. In the context of an object definition, id is identical to the current class or instance being defined, in contrast with a normal type that would indicate the class containing the declaration; in the context of an invocation of a method involving id typed arguments or return values, id denotes the actual receiver of the method.
For example, if a class Foo declares the following method:
id self; |
then the type of the expression
{ Foo a; [a self]; } |
is Foo. If there exists a class Bar which inherits from Foo, then the type of the expression
{ Bar a; [a self]; } |
is Bar, since it is a Bar that was the actual receiver of the self message (as far as the compiler knows).
The meta level of id can be shifted towards instances or classes, as can be seen in the following two method declarations from the State class.
<doc> Return a newly allocated instance of the receiving class. </doc> instance (id) alloc; <doc> Return the class of the receiving object. </doc> class (id) class; |
Thus, irrespective of the class of which the alloc method is invoked, the compiler knows that the object returned by alloc is an instance of the receiving class.
Similarly, the isa instance variable is declared by the State instance as
class (id) isa; |
Thus, in the context of a subclass of State, the isa has the type of the actual class object, not just the State class.