One of the nice things about Apple’s OS X for the Macintosh is that they include a free copy of Xcode, a very sweet graphical development environment allowing developers to make Cocoa applications using Objective-C.
The problem is, jumping straight into the Cocoa framework, even with tutorials, can be a daunting task if you’re not comfortable with Objective-C.
Yes, there are a number of books out there, but today I stumbled across, quite by accident, a fairly decent tutorial on Objective-C.
That got me thinking. In a world where we can easily pick up C++, C#, Java, Python, and Ruby… what is it about Objective-C that makes it hard to follow? Here’s what I think the major stumbling blocks are:
Notation Preconceptions Clouding C as the True Origin
In the classic examples, we think in terms of an object with methods and members, often using a dot-like syntax. As such, we tend to want to force fit Objective-C’s way of doing thing into some preconceived mold, and when the syntax doesn’t express that, things fall apart.
The Solution: Back off. Drop all the way back to C. Consider Objective-C nothing more than a well written pre-processor to useful object like extensions to the C programming language. Sure your implementation may very well be a compiler, but don’t think in those terms.
You’ve Got Classes Wrong
You’re used to thinking that a class is a data type. Don’t, think of it as a thing. In fact, Objective-C only needs to know a variable is a class, it doesn’t need to know which one or what it exposes. Classes are things whose primary role is to produce instances.
It’s Supposed To Feel Like Macro Magic
When you’re working on the guts of a class, you’ve got a lot of blocks that start with @class, @interface, @end, …. If it feels like something’s acting as a pre-processor and is converting that stuff into data structures and functions, it is. You’re not going to see pretty syntax that feels integrated into the language.
Hard Crunchy Outside, Soft Gooey Inside
A class exposes an interface, this is how the outside world sees and interacts with your class. Specifically, its your methods. And they’re all public. Get over it. Test. Only your members can be protected or private.
Remember, there are class-things and instance-things.
Declarations and Definitions
With C, there’s declarations that define the type and are often used for forward references; additionally, there are definitions where the memory is actually allocated and a value assigned.
Objective-C objects work similar. There’s an @interface / @end block that describes the object, its members, and its methods. And there’s an @implementation / @end block that actually contains the real code.
void * and id
A pointer in C, indicated by a *, points at a data type. If the pointer is given a void type, the compiler does no type checking. You know this. The id type holds a object, regardless what type it is.
Messages are not Methods
Any object can be sent any message. An object maps a message to a method. However, if there’s no mapping available, it can be handed to a general handler for the object — which can be clever and analyze the message.
Extended classes… and instances.
The mapping between message and method can be extended; you can think of it as subclassing. However, it’s possible to extend an instance. Meaning, a class might not respond to a message, while instance A does and instance B doesn’t.
Because messages are bound late to an object, and the magic is done with data structures rather than types, it’s possible to create a collection of methods and add them to a class, even pre-existing ones you don’t have source code for.
A protocol neither exposes an interface, nor does it provide an implementation. It is simply a named collection of method signatures which is attached to classes. Because any message can be sent to any object instance (or class), it is helpful to be able to “ask” if certain messages will be honored; that’s what protocols are for.
It’s Not Named Parameters
The syntax of a method may look odd, primarily because parameters appear to have additional text:
-(void) rotate:(String *)shape clockwise:(float)degrees;
In many modern languages, a signature can be overloaded. However, go back to the trick “What Would Macros Do?” In this case, any text that appears in front of a parameter is not a named parameter, but part of the method name. The above method would be the logical equivalent of
void rotate_clockwise( String *shape, float degrees ) in raw C.
Constructors / Destructors
In today’s languages, performing a
new allocates memory and initialized the object. Objective-C splits these into two discrete operations; this allows you to allocate memory from different heaps, as well as deferring expensive initializations – no bogus empty constructors here.
Note, you are also responsible for calling the superclass’s init, before doing your own init. If you have a method to deallocate the object, when done you need to call the superclass’s deallocation routine.
C requires you to take on more responsibility and pay attention to order; Objective-C classes require the same amount of vigilance.
Extra Data Types
Objective-C provides some helper data types, but some of them are tied quite strongly to the messaging framework.