< Previous PageNext Page >

The Root Class

Just by themselves, the Objective-C language and runtime are not enough to construct even the simplest object-oriented program, at least not easily. Something is still missing: a definition of the fundamental behavior and interface common to all objects. A root class supplies that definition.

A root class is so-called because it lies at the root of a class hierarchy—in this case, the Cocoa class hierarchy. The root class inherits from no other class, and all other classes in the hierarchy ultimately inherit from it. Along with the Objective-C language, the root class is primarily where Cocoa directly accesses and interacts with the Objective-C runtime. Cocoa objects derive the ability to behave as objects in large part from the root class.

Cocoa supplies two root classes: NSObject and NSProxy. Cocoa defines the latter class, an abstract superclass, for objects that act as stand-ins for other objects; thus NSProxy is essential in the distributed objects architecture. Because of this specialized role, NSProxy appears infrequently in Cocoa programs. When Cocoa developers refer to a root or base class, they almost always mean NSObject.

This section looks at NSObject, how it interacts with the runtime, and the basic behavior and interface it defines for all Cocoa objects. Primary among these are the methods it declares for allocation, initialization, memory management, introspection, and runtime support. These concepts are fundamental to an understanding of Cocoa.

In this section:

NSObject
Root Class—and Protocol
Overview of Root-Class Methods
Interface Conventions
Instance and Class Methods


NSObject

NSObject is the root class of most Objective-C class hierarchies; it has no superclass. From NSObject, other classes inherit a basic interface to the run-time system for the Objective-C language, and its instances obtain their ability to behave as objects.

Although it is not strictly an abstract class, NSObject is virtually one. By itself, an NSObject instance cannot do anything useful beyond being a simple object. To add any attributes and logic specific to your program, you must create one or more classes inheriting from NSObject or from any other class derived from NSObject.

NSObject adopts the NSObject protocol (see “Root Class—and Protocol”). The NSObject protocol allows for multiple root objects. For example, NSProxy, the other root class, does not inherit from NSObject but adopts the NSObject protocol so that it shares a common interface with other Objective-C objects.

NSObject, along with java.lang.Object, is the root class for all things Cocoa in Java, including Foundation and Application Kit.

Root Class—and Protocol

NSObject is the name not only of a class but of a protocol. Both are essential to the definition of an object in Cocoa. The NSObject protocol specifies the basic programmatic interface required of all root classes in Cocoa; thus not only the NSObject class adopts the identically named protocol, but the other Cocoa root class, NSProxy, adopts it as well. The NSObject class further specifies the basic programmatic interface for any Cocoa object that is not a proxy object.

A protocol such as NSObject is used in the overall definition of Cocoa objects (rather than including those protocol methods in the class interface) to make multiple root classes possible. Each root class shares a common interface, as defined by the protocols they adopt.

In another sense, NSObject is not the only “root” protocol. Although the NSObject class does not formally adopt the NSCopying, NSMutableCopying, and NSCoding protocols, it declares and implements methods related to those protocols. (Moreover, the NSObject.h header file, which contains the definition of the NSObject class, also contains the definitions of all four protocols mentioned above.) Object copying, encoding, and decoding are fundamental aspects of object behavior. Many, if not most, subclasses are expected to adopt or conform to these protocols.

Note: Other Cocoa classes can (and do) add methods to NSObject through categories. These categories are often informal protocols used in delegation; they permit the delegate to choose which methods of the category to implement. However, these categories on NSObject are not considered part of the fundamental object interface.

Overview of Root-Class Methods

The NSObject root class, along with the adopted NSObject protocol and other “root” protocols, specify the following interface and behavioral characteristics for all non-proxy Cocoa objects:

NSObject has several other methods, including class methods for versioning and posing (the latter lets a class present itself to the runtime as another class). It also includes methods that let you access runtime data structures, such as method selectors and function pointers to method implementations.

Interface Conventions

Some NSObject methods are meant only to be invoked while others are intended to be overridden. For example, most subclasses should not override allocWithZone: but they should implement init—or at least an initializer that ultimately invokes the root-class init method (see “Object Creation”). Of those methods that subclasses are expected to override, NSObject’s implementation either does nothing or returns some reasonable default value such as self. These default implementations make it possible to send basic messages such as init to any Cocoa object—even to an object whose class doesn’t override them—without risking a runtime exception. It’s not necessary to check (using respondsToSelector:) before sending the message. More importantly, the “placeholder” methods of NSObject define a common structure for Cocoa objects and establish conventions that, when followed by all classes, make object interactions more reliable.

Instance and Class Methods

The runtime system treats methods defined in the root class in a special way. Instance methods defined in a root class can be performed both by instances and by class objects. Therefore, all class objects have access to the instance methods defined in the root class. Any class object can perform any root instance method, provided it doesn’t have a class method with the same name.

For example, a class object could be sent messages to perform NSObject’s respondsToSelector: and performSelector:withObject: instance methods:

SEL method = @selector(riskAll:);
 
if ([MyClass respondsToSelector:method])
    [MyClass performSelector:method withObject:self];

Note that the only instance methods available to a class object are those defined in its root class. In the example above, if MyClass had re-implemented either respondsToSelector: or performSelector:withObject:, those new versions would be available only to instances. The class object for MyClass could perform only the versions defined in the NSObject class. (Of course, if MyClass had implemented respondsToSelector: or performSelector:withObject: as class methods rather than instance methods, the class would perform those new versions.)



< Previous PageNext Page >


© 2006 Apple Computer, Inc. All Rights Reserved. (Last updated: 2006-12-20)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.