Navigation

Home
Mac OS X Games
Shareware
Tutorials & Articles
Photo Gallery
Paintings
Animations and Images
Writing
Resources and Links


Whistle Stop Guide to Objective-C
By Andrew Sage

(This article first appeared on the CreateMacGames.org website.)

At first glance Objective-C can appear very confusing, and even slightly daunting, with all its [square brackets] after being used to C++. Here is a quick guide into what it all means to make that transition nice and easy Ð well that is the idea anyway.

Note: This guide was written to assist a C++ developer switch to Objective-C, but it gives enough of a guide for those without C++ experience.

What is Objective-C?

Objective-C is a set of object-oriented additions to the C language. At its core is the ANSI C language.

The components of Objective-C are the following:

Objects
Objects associate data and operations that are carried out on that data.

Methods
Methods are the actual operations that Objective-C applies to the data.

Messages
Messages are the way one instance of a method requests another method to perform an operation. As an example, [myCard display], asks the myCard object to perform the display operation.

Classes
Classes describe how objects are defined. Classes inherit variables and methods from a higher level class called super-class. A class that inherits some or all of the methods and variables of a class is called a sub-class. In Objective-C all classes are a sub-class of the super-class called NSObject.

Protocols

Protocols define a set of methods which a class must contain in order to conform to the said protocol. This allows you to be certain that a message sent to an object following the protocol will be able to accept and process the message.



Categories

Categories are a way to extend the functionality of objects. They are used to add additional methods to an object, however they cannot be used add additional instance variables. Using categories it is possible to override existing methods belonging to an object.


Remote Messages
Remote Message support the distribution of objects into different threads of execution and across different computers.

Persistence
Persistence allows objects and their data to persist after the instance that created the object has completed its execution.

Traditional programming languages call a function to perform an operation on an objectÕs data. Objective-C sends a message to an object asking it to perform one of its methods on itself.

Other Features

Objective-C delays the typing of language objects until the code is executed at run time.

Methods and classes may be added or removed at runtime.

The Actual Code

Below each section of code is a description about what it does. Hopefully this will not make things too scary.

The Header File

In C++ you have your class header (Card.h) that looks something like this:
Class CCard : public CObject
{
public:
	CCard();	// constructor
	CCard(int nValue, int nSuit);
	~CCard();	// destructor

	void SetSuit(int nSuit);
	int  GetSuit();

	void SetValue(int nValue);
	int GetValue();

// Attributes
private:
	int m_nSuit;
	int m_nValue;
	
};
In Objective-C your class header (Card.h) would look like the following:
@interface Card : NSObject
{
	int suit;
	int value;
}

- (Card*)init;

- (void) setCardWithValue:(int)theValue suit:(int)theSuit;

+ (Card*)initWithValue:(int)theValue suit:(int)theSuit;

- (int)suit;
- (void)setSuit:(int)theSuit;

- (int)value;
- (void)setValue:(int)theValue;

- (NSString *)description;
@end
So what does all this mean?

Everything between @interface and @end is the interface for the class.

The items between { and } are what is known as the instance variables.

Each of the Ð lines are the definitions of the methods that behave in the same way as C++ functions. Methods defined with a Ð are used by instances of the class, i.e. they are invoked when the instance receives a message.

The + line is the definition of a class method. They are sometimes called a factory method because they usually return a new instance of the class. Factory objects are not instances of a class and so cannot access the instance members. Methods defined with a + are used by the class itself, i.e. they are invoked when the class itself receives a message.

The Implementation File

The actual implementation of the class, the Card.cpp file, looks like this:
#include "Card.h"

CCard::CCard()
{
	m_nValue = 0;
	m_nSuit = 0;
}

CCard::~CCard()
{
}

CCard(int nValue, int nSuit)
{
	m_nValue = nValue;
	m_nSuit = nSuit;
}

void SetSuit(int nSuit)
{
	m_nSuit = nSuit;
}

int  GetSuit()
{
	return m_nSuit;
}

void SetValue(int nValue)
{
	m_nValue = nValue;
}

int GetValue()
{
	return m_nValue;
}
The Objective-C equivalent, this time Card.m, looks like this:
#import "Card.h"

@implementation Card

- (Card*) init
{
	self = [super init];

	[self setCardWithValue:0 suit:0];

	return self;
}

- (void) setCardWithValue:(int)theValue suit:(int)theSuit
{
	[self setValue:theValue];
	[self setSuit:theSuit];
}

+ (Card*)initWithValue:(int)theValue suit:(int)theSuit
{
	Card* thisCard = [[[Card alloc] init] autorelease];

	[thisCard setValue:theValue];
	[thisCard setSuit:theSuit];

	return thisCard;
}
- (void)dealloc
{
	[super dealloc];
}

- (int)suit
{
	return suit;
}

- (void)setSuit:(int)theSuit
{
	id old = suit;
	suit = [theSuit retain];
	[old release];
}

- (int)value
{
	return value;
}

- (void)setValue:(int)theValue
{
	id old = value;
	value = [theValue retain];
	[old release];
}

- (NSString *)description
{
	return [NSString stringWithFormat: @"Card value:%d suit:%d", value, suit];
}


@end
And all of the above means what exactly?

The first difference between Objective-C and C++ is that Objective-C source files use #import instead of #include to tell the compiler to look in the header file for the class definitions. #include can be used, but #import is preferable as it ensures the file is only included once.

Everything between the @implementation and @end is the implementation of the class.

The init method is where the object is initialised. This is equivalent to a C++ constructor. The self variable is exactly as it says, a reference to itself. Self is equivalent to this in C++.

When an object is initialised it has to call the init method of the class it is based on by using the self = [super init] line. Returning self returns a pointer to the newly created object.

The setCardWithValue method sets the instance variables for the object with the values passed in via the theValue and theSuit parameters.

The initWithValue method first creates a new instance of the object and then sets its suit and value using the theValue and theSuit parameters passed into it.

The dealloc method is where the object is released from memory. This is equivalent to a C++ destructor. The actual freeing from memory of the object is doen by calling the dealloc method of the base class. This is done by the [super dealloc] line.

The suit method returns the current value of the suit instance variable.

The setSuit method assigns a new value to the suit instance variable. The id old line creates a pointer to the existing instance variable. We use the type id as we are not bothered about the type of the instance variable. The next line sets the instance variable to a copy of the theSuit object that was passed into the method. Finally we free the old object from memory.

The value method returns the current value of the value instance variable.

The setValue method assigns a new value to the value instance variable. It behaves the same way as the setSuit method.

The description method returns details of the object as a text string. This text string can be used in outputting information about the object.

Creating the Object

Creating and using the class in C++ would be something like the following:
CCard cardOne;
or
CCard cardTwo(2, 4);
or
CCard* pCard = new CCard;
The Objective-C version would be as follows:
Card* cardOne = [[Card alloc] init];
or
Card* cardTwo = [Card initWithValue:2 suit:4];
The first version creates a new Card object and then calls its init method. A pointer to this object is then stored in cardOne. This is similar to Card* pCard = new Card in C++.

The second version creates a new Card object with a value of 2 and a suit of 4. cardTwo then points to this new object.

Using the Object

Calling a member function of a C++ class is as follows:
cardOne.GetSuit();
or
pCard->SetSuit(2);
In Objective-C it is as follows:
[cardOne suit];
or
[cardTwo setSuit:2];
The first version sends a message to the cardOne instance of the Card object requesting that the suit method be used. This will return the current value of the suit instance variable.

The second version sends a message to the cardTwo instance of the Card object requesting that the setSuit method be used and passes it the parameter of 2. This will set the suit instance variable to 2.

Well I hope that make things a bit easier for anyone switching over to use Objective-C.

Article Copyright (c) 2004 Andrew Sage


About the Author
Andrew Sage has been dabbling with games writing over the last 20 years on various platforms ranging from the Sinclair ZX Spectrum, Commodore Amiga, Windows, Palm and since February 2002, Mac OS X. During this time he has managed to complete a large percentage of projects started and even made a small amount of money selling some of his creations.

Currently he is working on, amongst other things, a book entitled Cocoa Puzzle Games: Learning Cocoa the Fun Way and actively seeking a publisher.

Article Copyright (c) 2004 Andrew Sage