I made a few minor tweaks to my LJ style (mostly in the stylesheet). It turns out that it looks fine in Opera, Phoenix, and Mozilla–but I looked at it with an older version of Netscape and some of the text was black (on a dark background) instead if yellow. I still do not know whether it looks good on Internet Exploder. I do not feel like taking time out of the day to install Crossover Office and track down an IE installer.
Okay kids, gather 'round as Uncle Enigma talks to you about C, C++, and Objective-C, and try not to fall asleep. In the beginning there was C, and it was good. People could write code that compiled, and they did not have to write it for a single CPU–it could compile anywhere. It was good, but it was not yet great. People wanted more. Object oriented languages sprung up here and there, but none were great enough to be truly called “great.” Two big players rose out of C, Objective-C and C++. One of them hit it big and one of them hit it not-so-big. The one you have heard of, of course, hit it big.
Warning: Geeky rant covering all sorts of technical minutiae follows…
Supposedly, they both started out as preprocessing macros to the C language. They both evolved into full-fledged languages, but C++ shed a lot of the awkward macro syntax. The development environment for the old NeXT cubes was Objective-C. The development environment for all (most) modern GUI operating systems is C++, with a few still in C. I have heard a lot of talk about how great and easy programming for NeXT and NextStep is, but never really got any explanations as to why or how. I have heard that OS X was built upon Steve Jobs' old NextStep architecture, but nothing more detailed than that. Well, now I possess a little bit of “mystery knowledge” (as Kate and Lisa would say) about NextStep, Objective-C, and OS X.
Yes, indeed, OS X is based on NextStep. In fact, all of the Foundation Framework (all the core stuff that does not touch a GUI anywhere–object datatypes, files, sockets, threads, etc.) and AppKit Framework (all the windows, buttons, panels, text fields, OpenGL, etc.) are copied almost directly from NextStep. How do I know? Because every object name and global function name is prefixed with “NS.” NSObject, NSNumber, NSString, NSPrintPanel, NSEvent, NSTextField, etc. It was a little bit of trivia in a footnote of a book somewhere that was just so satisfying to know.
I do have to say that I love the object model of NextStep. The objects and operations are extremely well though out. Threading and passing messages between threads are as easy as pie. Hooking up GUI to code is easy. I can see a few pretty good design patterns that were borrowed when Java was created (or maybe both NextStep and Java borrowed from someone else).
I also have to say that I am really annoyed by the syntax. Every single sane object oriented language I have every used uses dots to separate things. For instance: string.length() or window.getRectangle().setSize(300,200). Objective-C still has a lot of the old macro cruft and contains things in square brackets (sometimes I have to tell myself that this really is C and not LISP). For instance: [string length] or [[window getRectangle] setSize:300 height:200]. Yes, arguments are messy. The first one is after a colon immediately following the function name. Additional arguments are passed by name (but in the proper order), in the format “name:value.” [user setname:@”Brian” lastName:@”Enigma”]. Oh, I forgot to mention that @”….” is a macro that expands to a UTF8 Unicode string, which is what everything expects. On the one hand, it is really nifty that everything is automatically set up for multilanguage support. On the other hand, you have to remember to make all your constants multilanguage, or bad things happen.
While we are discussing C++ and Objective-C differences, let us talk about object scope and lifetime. When you create an object in C++ or Java (Window *w = new Window()), it is allocated and initialized. When you create an object in Objective-C, it is allocated, but not initialized. You have to explicitly initialize your object: Window *w = [[Window alloc] init]. Also, there is no method overloading. If you have two different constructors, one that is parameterless and one that takes parameters. In C++, you have no problem: Window *w = new Window(200,100) or Window *w = new Window(). In Objective-C, everything needs a different name, you you need multiple initializers. Window *w = [[Window alloc] initWithSize:200 height:100] or Window *w = [[Window alloc] init]. How annoying is THAT? It is even more so because of the multiple arguments.
Now, on the other hand, memory management is a little more nifty with Objective-C. In C++, you have to remember that everything you create must be destroyed. This is a simple enough concept, but gets a little more tricky when a function call creates something and returns it. Who is responsible for destroying the object–the calling function or the called function/object? Good documentation is required, and we all know that good documentation never happens until after the fact. Objective-C has not only initializers and destructors, but reference counts. You can initialize something, but you can also “retain” it, which ups the reference count. Nothing gets destroyed until the reference count reaches 0. Java does this internally, with reference counts and garbage collection–but I am not even going to touch that subject. There is a love/hate relationship between Java programmers and garbage collection. Objective-C also has a concept of memory pools. Since everything is derived from an NSObject (much like Java's “Object” class), NSObject defines the destructor routines. A memory pool is basically a collection of objects. When you (or a calling function) creates something, it can add it to the memory pool. When the memory pool gets gets destroyed, everything it is aware of is also destroyed (or at least told to decrement the reference count in case another thread has retained it and does not yet want it destroyed). While this works kind of like Java's garbage collection, it puts the programmer in control instead of letting the system randomly decide it is time to do garbage collection in the middle of a critical real-time operation. Serializing and deserializing objects is another concept shared with Java.
Objective-C's IDE is rather nifty. I am still trying to get used to the keyboard shortcuts–they are Mac shortcuts (Command-right to go to the end of line), and my brain has been filled with a number of other shortcuts (the end key in Windows, Ctrl-E in most of Unix, $ in vi). I am a huge fan of the Ctrl-E and $ since I do not have to move my fingers very far, in much the same way I like hotkeys for everything so I do not have to find the mouse then find the keyboard again. Mouse operations only take a few seconds each, but when you have to do it hundreds, if not thousands, of times a day it gets really old really fast. Anyway, back to the IDE. It is really just a GUI shell that sits atop a special version of gcc that understands Objective-C, gdb (which also understands the Objective-C object model), and a few other command line tools. As you are debugging, you can even pop open the console and see gdb doing its thing. You can even interact with it: (gdb) print-object [song description] or (gdb) print (int) [artist length]. Pretty nifty!
All-in-all, it takes quite a lot of getting used to the syntax, but the object model and overarching concepts are not too radical to your average C++/Java programmer. Some of the concepts “fix” concepts in C++ and some of them “break” things you get used to in C++. Admittedly, I have only written a “hello world” program and a currency calculator so far, but I have the basics down and have been picking up a lot by randomly reading sections of the API documentation. I think I might make an OpenGL “hello world” program next, with spinning 3D text and stuff.