1.10 Root Classes
A root
class is one with no parent class. Objective-C allows multiple root
classes, but you are most likely to use one supplied with your
compiler.
All Objective-C distributions provide a root class called
Object. This section describes the
Object supplied with the GNU runtime. The
Object class provided by Darwin is similar, but
Darwin users will be more likely to
use the NSObject root class that comes with the
Cocoa class library. (The
GNUstep library also provides an
NSObject root class almost identical to
Cocoa's.) This section describes the fields and
methods of both Object and
NSObject.
Both classes provide access to Objective-C features like reflection,
memory management, and archiving. Most of the classes you write will
inherit from one of these classes, so your objects will be able to
use these features.
 |
The runtime goes to some length to make class objects behave the same
as regular objects. In particular, they appear to inherit their
fields and methods from the root classes, so they share in the
properties described in this section.
|
|
1.10.1 Fields
Both
Object and NSObject
declare only one field, isa, whose type is
Class. This field is inherited by all their
descendants, which is critical to the operation of inheritance and
message dispatch. It points to the class object representing the
instance's class. See Section 1.9 earlier in this
book.
1.10.2 Methods
Root class methods are accessible from any
object that derives from the class—usually all regular objects
in a program. In addition, root class instance methods can be called on
class objects for it and its
subclasses—in other words, class objects appear to be instances
of their root class. (The runtime arranges for this; see Section 1.9.2 under Section 1.9.)
Because you can call root class instance methods on class objects,
the behavior of some instance methods described here has several
distinct, though consistent, cases:
The receiver is a regular object.
The receiver is a class object.
The receiver is a metaclass object (in the GNU runtime, where
metaclass objects are distinguished from class objects).
The root class method descriptions point these issues out where
useful.
Some root class methods are meant to be
overridden; others should not be. The
following sections note where you may or must override a method.
 |
Many root class methods (e.g., -respondsTo:)
return information about the receiver even when it's
an instance of a subclass. This makes it look like they are
automatically rewritten in each
subclass, or that your classes should
override them. In fact, the root class's
implementation makes use of runtime reflection to provide the
information required.
|
|
1.10.3 The Object Class
This section describes the methods provided by the GNU Object
class. The source code for these methods, available in
Object.m, gives a valuable view of how the
Objective-C runtime works.
1.10.3.1 Creating, copying, and freeing objects
Object provides the following methods to manage
the memory used for
objects.
You should never use the C functions malloc( ) and
free( ) to manage Objective-C objects. The earlier
Section 1.7 discusses how
to use these methods.
- +(id)new
-
Calls +alloc on the
class, then -init on the resulting instance, and
returns the result.
- +(id)alloc
-
Allocates, clears, and returns a pointer
to memory for a new instance of the receiver. Returns
nil on failure.
- +(id)initialize
-
Returns self. The
runtime calls this method before any instances of the receiving class
are created. Override to perform class-specific setup.
- -(id)init
-
Returns self. This
is the designated initializer for Object.
- -(id)copy
-
Calls -shallowCopy
then
-deepen on the resulting instance, and returns the
result. In Object this is the same as
-shallowCopy.
- -(id)shallowCopy
-
Returns a copy of
the receiver. Fields that are pointers are not traversed, just
duplicated in the new copy.
- -(id)deepen
-
Returns self.
Override to replace all fields that are pointers with new values.
Otherwise, -deepCopy and -copy
won't function correctly.
- -(id)deepCopy
-
Calls
-copy and returns the result.
- -(id)free
-
Releases
the
memory occupied by the receiver. Also zeroes the
isa pointer of the object. If the object is sent a
message at this stage, an immediate runtime error will occur. (Once
the memory has been reused, anything can happen.) Override to release
other resources held by the receiver.
1.10.3.2 Identifying objects and classes
Use
the
following methods to find out about an object's
identity, and to compare it with other objects:
- -(Class)class
-
If the
receiver is a regular object, returns the class object for the
receiver's class.
If the receiver is a class object, returns the receiver.
- -(Class)superClass
-
If the receiver is a regular object,
returns the class object for the parent class of the
receiver's class, or nil if
the receiver's class is a root class.
If the receiver is a class object, returns the class object for the
receiver's parent class, or
nil if the receiver represents a root class.
- -(MetaClass)metaClass
-
If the receiver is a regular object,
returns the metaclass object for the metaclass of the
receiver's class.
If the receiver is a class object, returns the metaclass object for
the metaclass of the receiver.
- -(const char*)name
-
Returns the name of the
receiver's class.
- -(id)self
-
Returns the receiver. You can get a class
object from the class's name with this method:
Class classobj = [MyClass self];
- -(unsigned int)hash
-
Returns an integer that can be used to
store the object in a hash table. If two objects are equal (as
reported by -isEqual:) they will have the same
hash value. However, two unequal objects may also share the same hash
value.
- -( BOOL )isEqual:( id ) obj
-
Returns YES if the
receiver and obj are equal as pointers,
otherwise returns NO. Override to implement
another relation, such as equality of contents.
- -( int )compare:( id ) obj
-
Returns one of the following values:
0, if [self
isEqual:obj]
returns YES.
-1, if the receiver's value (as a pointer) is less
than that of obj.
1, if the receiver's value (as a pointer) is greater
than that of obj.
Override this method if you want to compare your objects in a
different way.
1.10.3.3 Testing object type
Objective-C
minimizes the
differences between regular and class objects, but sometimes it is
helpful to know which is which. In addition, the
GNU runtime distinguishes between class
and metaclass objects. The following methods let you find out from an
object what kind it is:
- -(BOOL)isInstance
-
Returns
YES if the receiver is a regular object,
otherwise NO.
- -(BOOL)isClass
-
Returns
YES if the receiver is a class object,
otherwise NO.
- -(BOOL)isMetaClass
-
Returns
YES if the receiver is a metaclass object,
otherwise NO.
1.10.3.4 Testing inheritance and conformance
Use
the following
methods to find out an object's place in the
inheritance hierarchy:
- -( BOOL )isKindOf:(Class) classObj
-
If the receiver is an
ordinary object, returns YES if the
receiver's class is
classObj or a descendant of it,
NO otherwise.
If the receiver is a class object, returns YES
if classObj is the immediate metaclass of
the receiver, NO otherwise.
If the receiver is a metaclass, returns NO.
- -( BOOL )isKindOfClassNamed: ( const char *) className
-
Same as
-isKindOf:, but takes as a parameter the name of a
class instead of a class object.
- -( BOOL )isMemberOf:(Class) classObj
-
If the receiver is
an ordinary object, returns YES if the
receiver's class is
classObj, otherwise
NO.
If the receiver is a class or metaclass object, returns
NO.
- -( BOOL )isMemberOfClassNamed:( const char *) className
-
Same as
-isMemberOf:, but takes as a parameter the name of
a class instead of a class object.
- -( BOOL )conformsTo:(Protocol*) prot
-
Returns
YES if the class of the receiver adopts the
protocol directly, or if that class directly or indirectly inherits
from another class that does.
1.10.3.5 Information about methods
Use the instance methods listed here to ask
regular objects about instance methods, and class objects about class methods.
- +( BOOL )instancesRespondTo:( SEL ) sel;
-
Returns
YES if instances of the receiving class
respond to the selector sel, otherwise
NO. Does not take forwarding into account.
- -( BOOL )respondsTo:( SEL ) sel
-
Returns
YES if the receiver responds to the selector
sel, otherwise NO.
Does not take forwarding into account.
+(struct objc_method_description*)
descriptionForInstanceMethod:(SEL )sel
-
If instances of the receiving class
handle the method specified by sel, this
method returns a pointer to a description of the method; otherwise it
returns a NULL pointer.
The return type is defined as follows in
objc-api.h:
struct objc_method_description {
SEL name;
char* types;
};
The first member of the structure will be of little use since you
already have the selector. The second points to a zero-terminated
character string. The string takes the form of type specifiers (as
returned by the @encode directive) for the
return and parameter types, interleaved with numbers describing
offsets of the parameters in the stack frame.
-(struct objc_method_description*)
descriptionForMethod:(SEL )sel
-
If the
receiver handles the method specified by
sel, this method returns a pointer to a
description of the method; otherwise it returns a
NULL pointer.
- +( IMP )instanceMethodFor:( SEL ) sel
-
If instances
of the receiving class handle the method specified by
sel, this method returns a pointer to the
implementation of the specified method; otherwise a
NULL pointer. You can use this to get a
pointer to a method you want to call directly. See Section 1.15 for an example.
- -( IMP )methodFor:( SEL ) sel
-
If the receiver
handles the method specified by sel, this
method returns a pointer to the method's code;
otherwise a NULL pointer.
1.10.3.6 Sending messages
Use the following methods to send
messages when you won't
know until runtime which message to send:
-(id )perform:(SEL )sel
-
Sends to the receiver the message
specified by the selector sel. Since
selectors can be assigned to variables, one part of your code can
tell another which message to send.
-(id )perform:(SEL )sel
with:(id)obj1
-
The same as -perform: but also provides the
argument obj1 to the method being called.
-(id )perform:(SEL )sel
with:(id )obj1
with:(id )obj2
-
The same as -perform: but also provides two
arguments to the method being called.
-(retval_t)performv:(SEL )sel
:(arglist_t)args
-
Like the -perform:
methods, but takes a variable-length parameter list. Call this method
inside your class's -forward::
method to delegate the message to another object.
The return type is a typedef for
void*. The second parameter
describes the parameter types and values. You can treat this as an
opaque type; its declaration is in encoding.h.
-(retval_t)forward:(SEL )sel
:(arglist_t)args
-
Invokes
-doesNotRecognize. Override as described in Section 1.11 to implement message
forwarding. The parameter types are the same as for
-performv::.
1.10.3.7 Posing
The following methods let you change the
inheritance hierarchy at
runtime:
+(id )poseAs:classObj
-
Substitutes the
receiver for the class represented by
classObj. The receiver must be a subclass
of the class represented by classObj. The
receiver can't declare any new fields. Call this
method before creating any instances of the class represented by
classObj or sending it any messages.
This is a way, similar to using categories, to add or override
methods to an existing class. In contrast with a category, the posing
class can send a message to
super, which will execute the method in
the class represented by classObj.
- -(Class)transmuteClassTo:(Class) classObj
-
Sets the
isa pointer of the receiver to
classObj, and returns the previous value
of the pointer. This effectively converts the receiver to an instance
of the class represented by classObj. This
will only work if the receiver's class is a
descendant of the class represented by
classObj, and instances of the two classes
have the same size. If the call fails, it returns
nil.
1.10.3.8 Enforcing intentions
Each method in the following list generates a
runtime error. In each case, when you
call the method, pass in the _cmd variable, which
the runtime sets up to be the selector of the method you are in.
-(id )subclassResponsibility:(SEL )sel
-
Call this in a method that you require
subclasses to override and implement.
-(id )notImplemented:(SEL )sel
-
Call this in a
method that you have deliberately left unfinished.
-(id )shouldNotImplement:(SEL )sel
-
Call this
in a method that you inherit (and override) but that makes no sense
for your subclass to support.
1.10.3.9 Error handling
The following functions are used for error handling. See Section 1.8 for more information
about their usage.
-(id )doesNotRecognize:(SEL )sel
-
Generates a
runtime error by invoking the
-error: method on
self. The runtime sends this message to an
object when the object has failed to respond to, or forward, a
message.
-(id )error:(const char *)format ,...
-
Writes an error message
to the system log (via the syslog( ) call) and
exits the program. The runtime calls this method on
self for a variety of error conditions.
Override as described in Section 1.8 to customize error handling
for a class.
1.10.3.10 Archiving
The GNU
runtime
provides the type
TypedStream for reading and writing objects to and
from archives. Section 1.13 describes this type and its use in saving and restoring
objects. The following methods support archiving:
-(id)awake
-
Does nothing and returns
self. Called by the runtime when an object has
been reconstructed. Override to customize behavior when your objects
are restored.
-(id )write:(TypedStream*)stream
-
Writes the receiver to
the specified stream.
-(id )read:(TypedStream*)stream
-
Sets the receiver's
fields by reading from the specified stream.
+(id )setVersion:(int )version
-
Sets the class version number.
+(int)version
-
Returns the class's
version number, or zero if it has never been set.
+(int )streamVersion:(TypedStream*)stream
-
Returns the version number of the
typed stream.
1.10.4 The NSObject Class
NSObject supports most of the features of
Object and adds others. Often the
NSObject version of a method will have a more
specifically typed return value. For example,
-class is declared to return a
Class and not just an id.
In defining NSObject,
Cocoa first declares the
NSObject protocol. (It can be confusing that the
class and protocol have the same name; they live in different
namespaces.) This allows for other root classes. As long as they
implement the NSObject protocol, they can be used
in contexts that depend on the methods that
NSObject implements.
The NSObject class implements the
NSObject protocol along with other useful methods
that its descendants may want but that are not part of the protocol
and are not important for interchangeability.
 |
Cocoa also declares categories for NSObject, such
as NSComparisonMethods,
NSURLClient, and others, comprising dozens of
additional methods. This handbook discusses a few of these categories
(NSCoding, NSKeyValueCoding)
separately, but omits them from this section.
|
|
In the following sections, the methods are grouped by topic, and
marked as being part of the NSObject protocol or
class.
1.10.4.1 Creating, copying, and freeing objects
Section 1.7 discusses
how to use the following methods, which create objects, copy objects,
and free the memory used by objects:
+(id)alloc
-
Allocates,
clears,
and returns a pointer to memory for a new instance of the receiver.
Memory comes from the default zone. Returns
nil on failure. (NSObject
class)
+(id )allocWithZone:(NSZone*)zone
-
Same as alloc, but
uses a specific region of memory.
NSZone is not a
class but a C type that you should treat as opaque. You can get the
zone of an object with the -zone method. You may
improve cache performance by creating related objects in the same
zone. Passing in a nil parameter means memory
will be allocated from the default zone. (NSObject
class)
+(void)initialize
-
Sent
by the runtime before the class or any of its descendants is sent a
message by the program. Each class gets the message exactly once, and
superclasses get the message before subclasses. The
NSObject implementation does nothing. Override
(first passing the call to super) to perform
per-class setup. (NSObject class)
-(id)init
-
Returns self. This
is the designated initializer for NSObject. The
Section 1.7 discusses
overriding this method. (NSObject class)
+(id)new
-
Calls +alloc, then
-init on the resulting instance, and returns the
result. (NSObject class)
+(id )copyWithZone:(NSZone*)zone
-
Returns
the
receiver since class objects are unique. Ignores the parameter.
Don't override. (NSObject class)
+(id )mutableCopyWithZone:(NSZone*)zone
-
Returns
the receiver since class objects are unique. Ignores the parameter.
Don't override. (NSObject class)
-(id)copy
-
Calls
-copyWithZone: with a nil zone
parameter. NSObject doesn't
implement that method (only the class method of the same name) but
many Cocoa classes do. Your class will have to implement
-copyWithZone: in order to use
-copy. The Section 1.7 discusses how to do
this.
-(id)mutableCopy
-
Calls
-mutableCopyWithZone: with a
nil zone parameter.
NSObject doesn't implement that
method (only the class method of the same name) but many Cocoa
classes do. Your class will have to implement
-mutableCopyWithZone in order to use
-mutableCopy. The Section 1.7 discusses how to do
this. (NSObject class)
-(void)dealloc
-
Deallocates
the
memory used to store the receiver. Override to release any additional
resources managed by your object. Don't call
-dealloc directly if you are using retain/release
memory management. (See Section 1.12.)
(NSObject class)
+(void)load
-
Called by the runtime when a class or
category is set up for use by the runtime. Deprecated in favor of the
+initialize method. (NSObject
class)
1.10.4.2 Identifying objects and classes
Use
the
following methods to find out about an object's
identity, and to compare it with other objects:
-(Class)class
-
Returns the class object for the
receiver's class. (NSObject
protocol)
-(Class)superclass
-
Returns the class object of the
receiver's parent class.
(NSObject protocol)
-(NSString*)description
-
Returns a string describing the state of
the receiver. The NSObject implementation prints
the class name and the runtime address of the instance. Override to
provide a string the runtime will use when you print an object using
the %@ formatting descriptor with NSLog(
). (NSObject protocol)
-(id)self
-
Returns the receiver. You can get a class
object from the class's name with this method:
Class circleClass = [Circle self];
(NSObject protocol)
-(unsigned)hash
-
Returns an integer that can be used to
store the object in a hash table. If two objects are equal (as
reported by the -isEqual: method) they will have
the same hash value. However, two unequal objects may also share the
same hash value. (NSObject protocol)
-(BOOL)isEqual:(id)object
-
Returns YES if the
receiver and object are equal as pointers,
otherwise returns NO. Override to provide
different semantics, such as equality of contents.
(NSObject protocol)
+(Class)class
-
Returns the class object that represents
the receiver, not (as you might expect) the metaclass object of the
metaclass of the receiver. This means that [MyClass
class] and [MyClass self] return the
same value; the second expression is probably more clear.
(NSObject class)
+(NSString*)description
-
Returns the name of the class.
(NSObject class)
+(void)setVersion:(int) version
-
Sets the class version number.
(NSObject class)
+(int)version
-
Returns the class's
version number, or zero if it has never been set.
(NSObject class)
+(Class)superclass
-
Returns the class object representing the
receiver's parent class.
(NSObject class)
1.10.4.3 Testing inheritance and conformance
Use
the following
methods to find out about an object's place in the
inheritance hierarchy:
+(BOOL )conformsToProtocol:(Protocol*)prot
-
Returns
YES if the receiver adopts
prot directly or inherits directly or
indirectly from another class that does. (NSObject
class)
-(BOOL )isKindOfClass:(Class)C
-
If the receiver
is an ordinary object, returns YES if the
receiver's class is represented by
C or is a descendant of the class
represented by C,
NO otherwise.
If the receiver is a class object, returns YES
if C represents
NSObject, NO otherwise.
(This is consistent with the special property that class objects
appear to be instances of the root object class.)
If the receiver is a metaclass object, returns
YES if C represents
NSObject or
NSObject's metaclass,
NO otherwise.
(NSObject protocol)
-(BOOL )isMemberOfClass:(Class) C
-
Is part of the
NSObject protocol, and does one of the following:
If the receiver is an ordinary object, returns
YES if C represents
the receiver's class, otherwise
NO.
If the receiver is a class object, returns YES
if C represents the
receiver's metaclass, otherwise
NO.
If the receiver is a metaclass object, returns
YES if C represents
NSObject's metaclass, otherwise
NO.
(NSObject protocol)
-(BOOL )conformsToProtocol:(Protocol*)prot
-
Returns
YES if the class of the receiver adopts the
protocol directly, or directly or indirectly inherits from another
class that does. (NSObject protocol)
-(BOOL)isProxy
-
Returns NO. (The
NSProxy class also implements this method, and
returns YES.) (NSObject
protocol)
1.10.4.4 Information about methods
Use the instance methods listed here to ask
regular objects about instance methods, and class objects about
class methods.
+(BOOL )instancesRespondToSelector:(SEL )sel
-
Returns YES if
instances of the receiving class respond to the selector
sel, otherwise NO.
Does not take forwarding into account. (NSObject
class)
+(IMP )instanceMethodForSelector:(SEL )sel
-
If
instances of the receiving class handle the method specified by
sel, returns a pointer to the
implementation of the specified method. You can use this to get a
pointer to a method you want to call directly. Section 1.15 gives an example.
The Cocoa documentation says that if instances of the receiving class
do not handle the specified method, a runtime error occurs. Instead,
an apparently valid pointer is returned. You should use code like the
following to test for errors:
IMP imp = NULL ;
if ([ClassName instancesRespondToSelector:sel ])
imp = [ClassName
instanceMethodForSelector:sel ];
After executing these instructions, imp
will still be NULL if the
class's instances do not handle the method specified
by sel. (NSObject class)
+(NSMethodSignature*)
instanceMethodSignatureForSelector:(SEL )sel
-
If instances of the receiving class
handle the method specified by sel,
returns a description of the method's signature for
the specified method; otherwise returns nil.
(NSObject class)
-(IMP )methodForSelector:(SEL )sel
-
If the
receiver handles the method specified by
sel, this method returns a pointer to the
method's code. You can use this to get a pointer to
a method you want to call directly. Section 1.15 gives an example.
The Cocoa documentation says that if the receiver does not handle the
specified method, a runtime error occurs. Instead, an
apparently-valid pointer is returned. You should use code like the
following to test for errors:
IMP imp = NULL ;
if ([obj respondsToSelector:sel ])
imp = [obj methodForSelector:sel ];
After executing these instructions, imp
will still be NULL if the receiver does not
handle the method specified by sel.
(NSObject class)
-(NSMethodSignature*)methodSignatureForSelector:(SEL )sel
-
If
the receiver handles the method specified by
sel, this method returns a description of
the method; otherwise it returns nil.
(NSObject class)
-(BOOL )respondsToSelector:(SEL )sel
-
Returns
YES if the receiver responds to the selector
sel; otherwise NO. Does not take forwarding
into account. (NSObject protocol)
1.10.4.5 Sending messages
Use
the following methods to send messages when
you won't know until runtime which message to send:
-(id )performSelector:(SEL )sel
-
Sends to the
receiver the message specified by the selector
sel. Since selectors can be assigned to
variables, one part of your code can tell another which message to
send.
-(id )performSelector:(SEL )sel
withObject:(id )obj1
-
The same as -performSelector:, but also provides
the argument obj1 to the method being
called.
-(id )performSelector:(SEL )sel
withObject:(id ) obj1
withObject:(id )obj2
-
The same as -performSelector:, but also provides
two arguments to the method being called. If you need to pass more
than two parameters, construct an NSInvocation
instance. Section 1.11
gives an example. (NSObject protocol)
-(void )forwardInvocation:(NSInvocation*)inv
-
Invokes
-doesNotRecognizeSelector:. Section 1.11 describes how to
override this to implement message forwarding.
(NSObject class)
1.10.4.6 Posing
This method lets you modify the
inheritance hierarchy at
runtime:
+(void )poseAsClass:(Class)classObj
-
Substitutes the
receiver for the class represented by
classObj. The receiver must be a subclass
of the class represented by classObj. The
receiver can't declare any new fields. You should
call this method before creating any instances of the class
represented by classObj or sending it any
messages.
This is a way, similar to using categories, to add or override
methods to an existing class. In contrast with a category, the posing
class can send a message to
super and execute
the method in the class represented by
classObj. (NSObject
class)
1.10.4.7 Error handling
The following functions are used for error
handling. See Section 1.8
for more information about their usage.
-(void )doesNotRecognizeSelector:(SEL )sel
-
Raises an
NSInvalidArgument exception. The runtime sends this
message to an object when the object has failed to respond to or
forward a message.
You can "un-implement" a method as
follows:
-(void ) methodName {
[self doesNotRecognizeSelector: _cmd];
}
The class implementing this code will now behave as if it had no
methodName.
You could also make an object handle any message without failing by
overriding -doesNotRecognizeSelector:, but you
should override -forwardInvocation: instead.
(NSObject class)
1.10.4.8 Archiving
These
are peripheral methods that support saving
objects to disk and restoring them. Section 1.13 provides more
information on this topic.
-(id )awakeAfterUsingCoder:(NSCoder*)coder
-
Returns
the receiver. Called by NSCoder when it has
decoded the receiver. Override this to return some other object. You
are responsible for releasing the receiver if you return a different
object. (NSObject class)
-(Class)classForCoder
-
Returns the
receiver's class. Override to substitute another
class during archiving. Called by NSCoder.
(NSObject class)
-(id )replacementObjectForCoder:(NSCoder*)coder
-
Returns self.
Override to substitute another object for the receiver during
archiving. Called by NSCoder.
(NSObject class)
1.10.4.9 Reference counting
These methods support reference counting or return
information about an object's allocation. See Section 1.12 for more
information.
-(id)retain
-
Increments the
receiver's reference count and returns the receiver.
(NSObject protocol)
-(unsigned)retainCount
-
Returns the receiver's
reference count. (NSObject protocol)
-(oneway void)release
-
Decrements
the
receiver's reference count, and sends it the
-dealloc message if the count reaches zero. The
oneway keyword specifies that the caller can
send the message asynchronously. (See Section 1.6.)
(NSObject protocol)
-(id)autorelease
-
Adds the receiver to
the current autorelease pool. Returns the receiver.
(NSObject protocol)
-(NSZone*)zone
-
Returns the memory zone in which the
receiver was allocated.
NSZone is not a class but a C type that you
should treat as opaque. You can use the value returned by this method
as a parameter to -copyWithZone: or -allocWithZone:.
Cocoa creates a default zone when a program starts up, and normally
you will allocate objects from this zone. You may be able to improve
cache behavior by creating related objects in the same zone. See the
Cocoa documentation for NSCreateZone(
) and related functions.
(NSObject protocol)
|