Recently I have been attempting a little light MacOSX programming, to see if the grass really is greener over the fence. This means learning Objective-C, here are some random notes I made along the way (warning: much esoteric geekery ahead)
UPDATE: I have had some more thoughts, read them here.
This is actually a bit of a pain. Because Objective-C code tends to be dynamically linked with all sorts of frameworks at runtime, name collisions are not picked up until your program does something weird. The recommended approach of naming classes with a unique prefix is NSUglyAsSin.
C++ namespaces are great for statically linked stuff, but I think Java’s notion of packages works better for dynamically loaded classes.
Obj-C lies way down towards the do-everything-at-runtime end of the spectrum. This allows for some truly great code reuse, and makes other object systems like COM look inflexibly stupid. This does cause problems during development though – even attempting to call a method that doesn’t exist gets you a mild warning from the compiler, and sometimes not even that.
Both Objective-C and Java were designed with user interfaces in mind. When looking at Cocoa, which is basically NextStep, I was slightly surprised at how much of Java’s Swing was obviously influenced by NextStep as well. The controls work in much the same way, although the programming interfaces themselves are different.
Java is more strongly typed (strongly typeder?) than Obj-C, so when setting a handler for a button, the object must implement the ButtonHandler interface (or whatever, I can’t be bothered looking it up now). Obj-C is much more dynamic and takes it on your honour that the object you assign to handle a control actually implements the required methods. This is great for designing user interfaces, since you can add a whole bunch of actions and implement the details later. The user interface will be linked up to your class when your program is loaded (and often only when the window is first displayed), so any problems are going to be a surprise!
Both Java and Obj-C like to “strongly suggest” naming conventions for standard getter and setter methods. I don’t particularly like this kind of thing, but I guess it makes some things simpler and makes hooking up user interface to class members easy, but it’s prone to error.
To use technical jargon, Obj-C is polymorphic up the wazoo. Unlike C++, or even Java, classes do not have to derive of a common base class (or Java-style interfaces) to share programming interfaces. If you want to put a whole bunch of objects in a list and call printObjectToScreen on each one, Obj-C is not going to tell you not to just because the some of the objects are NSOil and some are XQWater. Even putting a object that doesn’t have a printObjectToScreen method in the list is not necessarily a fatal error, objects can catch and handle attempts to call unknown methods. Also, if you are feeling really clever you can add methods to a class at runtime.
With all the runtime inspection going on, Objective-C could use decorations to add user-specified metadata to a class. Perhaps there is a way of achieving the same result somehow, but I haven’t found it yet.
Coming from C++ and Java, the syntax of Objective-C is strange. You end up with method calls like:
[[inumber alloc] initWithReal: [point getX] andImaginary: [point getY]]
This is all very well and good, but is it clearer than:
I don’t think so.
Also note that Obj-C looks like it should have named parameters but it doesn’t, all parameters must be present and in the order that the class defines them in. Methods are called at runtime based on the names of all parameters, so the above example’s signature is initWithReal:andImaginary – there is a certain neatness to this approach.
Memory management is done in Obj-C with reference counts that have to be updated manually. This is a huge pain in the neck, although the auto-realease pools help somewhat. These work particularly well in UI code, since the autorelease pool is cleaned up after each UI event has been handled.
The language is really crying out for garbage collection, some compilers already do this and Apple is added it to MacOS in the next version of the OS.
Obj-C does not have operator overloading. No big deal.
No templates, but they are not so necessary in Obj-C’s more dynamic class system.
The great thing about C++ is that is possible to create really bullet-proof classes. You can ensure that your class is constructed properly, copied properly, and cleaned up properly. There are no such guarantees in Obj-C-land, the concept of a constructor is based more on convention than any compiler constraints, all sorts of things can go wrong. Since Obj-C objects never live on the stack, it is impossible to have things cleaned up in a defined order.