Up: A Tour Through the Standard W3Kit Main Routine

A 10-Minute Introduction to Objective-C

Objective-C is a powerful, easy-to-learn, object-oriented extension to C. Unlike in C++, advanced object-oriented features like dynamic binding, run-time type identification, and persistence are standard features in Objective-C which apply universally and work well together. Moreover, the support for descriptive message names (a la SmallTalk) makes Objective-C code easy to read and understand. Objective-C is supported by the GNU and NeXTSTEP C compilers.

This section introduces the syntax of Objective-C through a simple example of a custom 2D widget for W3Kit. For more detailed information, take a look at Gerrit Huizenga's course notes and the Objective-C FAQ.

Understanding the Class Header File

Here is the class header file, DotView.h:

    #import <W3Kit/W3PostScript.h>

    @interface DotView:W3PostScript
    {
        Point2 dot_position;
        float dot_radius;
    }

    - (float)dotRadius;
    - setDotRadius:(float)r;
    - takeDotRadiusFrom:sender;

    @end

Explanations:

#import <W3Kit/W3PostScript.h>

Incorporates the header file of the superclass, W3PostScript. #import is like #include except that it won't include the same file twice. This obviates the need for the usual C #ifndef hack in Objective-C headers.

@interface DotView:W3PostScript { ... } ... @end

Declares DotView to be a subclass of W3PostScript, with additional instance variables declared between the following braces, and additional messages declared before the @end.

- (float)dotRadius;
- setDotRadius:(float)r;
- takeDotRadiusFrom:sender;

A '-' introduces a declaration of a method that will be sent to instances of the class. Each argument gets its own descriptive name (which may be empty for later args), followed by a colon. A good but simple example of the use of descriptive argument names is the List message

    - insertObject:anObject at:(unsigned int)index;
C type-casting notation is used to declare the argument and return types. This cast may be omitted if the argument or return is of type `id', the universal object type.

In Objective-C, classes are objects too, and messages declared with a '+' instead of '-' will be sent to the class object rather than to its instances.

Understanding the Class Implementation File

Here is the start of the class implementation file, DotView.m, which closes with @end just like the header file:

    #import "DotView.h"

    @implementation DotView

    - init
    {
        if(![super init]) return nil;

        // Let x and y initially run between -1 and 1.
        [self setDrawSize:2.0 :2.0];
        [self setDrawOrigin:-1.0 :-1.0];

        // Set initial dot position.
        dot_position.x = dot_position.y = 0.0;
        return self;
    }

Explanations:

- init

Objective-C makes strong use of dynamic binding to simplify many tasks. For example, in W3Kit, widgets display themselves in a fill-out form via the -printHtml method. Nevertheless, custom 2D drawing widgets only have to override the -drawPostScript method, which contains the widget's PostScript drawing commands. That's because the -drawPostScript message, called inside the base class implementation of -printHtml, is dynamically bound.

As a more basic example, to create a DotView instance, you'd normally call [DotView new], which both allocates and initializes a new instance. However, as a subclass, DotView only has to override the initialization part, which is the -init method.

There are a number of other standard object messages that classes will want to be sure to correctly implement. See the header file <objc/Object.h> that comes with your compiler for general standards, and the section on widget design for W3Kit-specific standards.

if(![super init]) return nil;
[self setDrawSize:2.0 :2.0];

Objective-C message calls, which are enclosed in square brackets, function as ordinary C expressions, and can be used anywhere that C expressions can. The first part of the message call expression is the object that should receive the message (which can be any expression of type id). The second part lists the arguments, each preceded by its descriptive name and a colon.

Here we are sending additional messages to the receiver of the current message, which is referred to as self. In the first case, however, we want to call the inherited -init message (calling [self init] would be an infinite loop). This is done by using the name super for the current receiver instead of self.

Note that nil is the object equivalent of NULL.

dot_position.x = dot_position.y = 0.0;

Instance variables of the receiver of the current message can be accessed directly by name. It is neither necessary nor encouraged to say self->dot_position.x.

return self;

The -init message must return the newly initialized object, if successful. In general, though, when a message returns the default `id' type, it is traditional to return self. This allows nesting of messages, like [[obj msg1] msg2].

// Let x and y initially run between -1 and 1.

Objective-C allows C++ style comments that run until the end of the line.


Up: A Tour Through the Standard W3Kit Main Routine

[HOME] The Geometry Center Home Page

Author: Paul Burchard
Comments to: webmaster@www.geom.uiuc.edu
Created: Apr 18 1994 --- Last modified: Jun 18 1996