Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page > Hide TOC

Class Implementation

The definition of a class is structured very much like its declaration. It begins with the @implementation directive and ends with the @end directive:

@implementation ClassName : ItsSuperclass
{
    instance variable declarations
}
method definitions
@end

However, every implementation file must import its own interface. For example, Rectangle.m imports Rectangle.h. Because the implementation doesn’t need to repeat any of the declarations it imports, it can safely omit:

This simplifies the implementation and makes it mainly devoted to method definitions:

#import "ClassName.h"
 
@implementation ClassName
method definitions
@end

Methods for a class are defined, like C functions, within a pair of braces. Before the braces, they’re declared in the same manner as in the interface file, but without the semicolon. For example:

+ alloc
{
    ...
}
 
- (BOOL)isfilled
{
    ...
}
 
- (void)setFilled:(BOOL)flag
{
    ...
}

Methods that take a variable number of arguments handle them just as a function would:

#import <stdarg.h>
 
 ...
 
- getGroup:group, ...
{
    va_list ap;
    va_start(ap, group);
    ...
}

In this section:

Referring to Instance Variables
The Scope of Instance Variables


Referring to Instance Variables

By default, the definition of an instance method has all the instance variables of the object within its scope. It can refer to them simply by name. Although the compiler creates the equivalent of C structures to store instance variables, the exact nature of the structure is hidden. You don’t need either of the structure operators (. or ->) to refer to an object’s data. For example, the following method definition refers to the receiver’s filled instance variable:

- (void)setFilled:(BOOL)flag
{
    filled = flag;
    ...
}

Neither the receiving object nor its filled instance variable is declared as an argument to this method, yet the instance variable falls within its scope. This simplification of method syntax is a significant shorthand in the writing of Objective-C code.

When the instance variable belongs to an object that’s not the receiver, the object’s type must be made explicit to the compiler through static typing. In referring to the instance variable of a statically typed object, the structure pointer operator (->) is used.

Suppose, for example, that the Sibling class declares a statically typed object, twin, as an instance variable:

@interface Sibling : NSObject
{
    Sibling *twin;
    int gender;
    struct features *appearance;
}

As long as the instance variables of the statically typed object are within the scope of the class (as they are here because twin is typed to the same class), a Sibling method can set them directly:

- makeIdenticalTwin
{
    if ( !twin ) {
        twin = [[Sibling alloc] init];
        twin->gender = gender;
        twin->appearance = appearance;
    }
    return twin;
}

The Scope of Instance Variables

Although they’re declared in the class interface, instance variables are more a matter of the way a class is implemented than of the way it’s used. An object’s interface lies in its methods, not in its internal data structures.

Often there’s a one-to-one correspondence between a method and an instance variable, as in the following example:

- (BOOL)isFilled
{
    return filled;
}

But this need not be the case. Some methods might return information not stored in instance variables, and some instance variables might store information that an object is unwilling to reveal.

As a class is revised from time to time, the choice of instance variables may change, even though the methods it declares remain the same. As long as messages are the vehicle for interacting with instances of the class, these changes won’t really affect its interface.

To enforce the ability of an object to hide its data, the compiler limits the scope of instance variables—that is, limits their visibility within the program. But to provide flexibility, it also lets you explicitly set the scope at three different levels. Each level is marked by a compiler directive:

Directive

Meaning

@private

The instance variable is accessible only within the class that declares it.

@protected

The instance variable is accessible within the class that declares it and within classes that inherit it.

@public

The instance variable is accessible everywhere.

@package

On 64-bit, an @package instance variable acts like @public inside the image that implements the class, but @private outside.

This is analogous to private_extern for variables and functions. Any code outside the class implementation’s image that tries to use the instance variable will get a link error. This is most useful for instance variables in framework classes, where @private may be too restrictive but @protected or @public too permissive.

This is illustrated in Figure 2-1.


Figure 2-1  The scope of instance variables

Figure 2-1 The scope of instance variables

A directive applies to all the instance variables listed after it, up to the next directive or the end of the list. In the following example, the age and evaluation instance variables are private, name, job, and wage are protected, and boss is public.

@interface Worker : NSObject
{
    char *name;
@private
    int age;
    char *evaluation;
@protected
    id job;
    float wage;
@public
    id boss;
}

By default, all unmarked instance variables (like name above) are @protected.

All instance variables that a class declares, no matter how they’re marked, are within the scope of the class definition. For example, a class that declares a job instance variable, such as the Worker class shown above, can refer to it in a method definition:

- promoteTo:newPosition
{
    id old = job;
    job = newPosition;
    return old;
}

Obviously, if a class couldn’t access its own instance variables, the instance variables would be of no use whatsoever.

Normally, a class also has access to the instance variables it inherits. The ability to refer to an instance variable is usually inherited along with the variable. It makes sense for classes to have their entire data structures within their scope, especially if you think of a class definition as merely an elaboration of the classes it inherits from. The promoteTo: method illustrated earlier could just as well have been defined in any class that inherits the job instance variable from the Worker class.

However, there are reasons why you might want to restrict inheriting classes from directly accessing an instance variable:

To limit an instance variable’s scope to just the class that declares it, you must mark it @private. Instance variables marked @private are only available to subclasses by calling public accessor methods, if they exist.

At the other extreme, marking a variable @public makes it generally available, even outside of class definitions that inherit or declare the variable. Normally, to get information stored in an instance variable, other objects must send a message requesting it. However, a public instance variable can be accessed anywhere as if it were a field in a C structure. For example:

Worker *ceo = [[Worker alloc] init];
ceo->boss = nil;

Note that the object must be statically typed.

Marking instance variables @public defeats the ability of an object to hide its data. It runs counter to a fundamental principle of object-oriented programming—the encapsulation of data within objects where it’s protected from view and inadvertent error. Public instance variables should therefore be avoided except in extraordinary cases.



< Previous PageNext Page > Hide TOC


Last updated: 2008-02-05




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.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice