Objective-C
Objective-C, or Obj-C is an object oriented programming language implemented as an extension to C. It is used primarily on Mac OS X and GNUstep, and was the previously primary language used in NeXTSTEP and OpenStep.
History
In the 1980's common software engineering practice was based on structured programming. Structured programming was implemented in order to help "break down" programs into smaller parts, primarily to make them easier to work on as they grew increasingly large. However the power of the computers and the tasks they were being used for quickly overwhelmed the abilities of structured programming to solve them.
Many saw object oriented programming as a potential solution to the problem. In fact Smalltalk had already addressed many of these engineering issues, and some of the most complex systems in the world were Smalltalk enviornments. On the downside Smalltalk used a Virtual machine to run in, one that was very large and tended to require huge (for the time) amounts of memory, or run very slowly.
OO in general became very much in vogue for a time, perhaps before it was ready. People would oversell the advantages of OO, and attempt projects that were simply not reasonable. Worse, many of the tools were immature or had unrealistic requirements. It wasn't long before a backlash started and people rejected OO as yet another problem.
In the end the engineering community as a whole seemed to adopt a curious attitude. The common concensus was there was no way out of the software engineering problem, because software was fundamentally different than tangible goods, like cars.
Obj-C was created primarily by Brad Cox in the early 1980s. He had become interested in the problems of true reusability in software design and programming. In order to demonstrate that real progress could be made, Cox set about to show that making interchangeable software components really needed only a few practical changes to existing tools. Specifically they needed to support objects in a flexible manner, come supplied with a set of libraries that was actually usable, and allow for the code and any resources needed by the code to be bundled into a single cross-platform format.
The main description of Objective-C in its original form was published in his book, Object-oriented Programming, An Evolutionary Approach in 1986. Cox was careful to point out that there is more to the problem than the language, ut it appears this fell on deaf ears. Instead the system found itself compared on a feature-for-feature basis with other languages, missing the forest for the trees.
Language basics
Objective-C is a very "thin" layer on top of C. In fact it includes only one syntax change and about a dozen new keywords. The syntax change is for calling methods on objects, and is based on Smalltalk as opposed to C++. The code:
int doSomething (int i) { return squareRoot(i); }
from the C world would become:
- (int) doSomething: int i { return [self squareRoot: i]; }
This may look like a bad idea all around, but it did have one redeeming value; named parameters:
- (int)changeColorWithRed:int r Green: int g Blue: int b
which would be invoked thus:
[myColor changeColorWithRed:5 Green:5 Blue:5];
Objective-C is a dymamically typed language, as is Smalltalk. As with other dynamically typed languages, there is the potential problem of an endless stream of run-time errors that come from sending the wrong message to the wrong object. However Objective C allows the programmer to optionally identify the class of an object, and in those cases the compiler will apply strong-typing methodology. In fact most programs use this extensively in order to avoid these problems.
However when one does need dynamic typing, it becomes tremendously powerful. Consider a simple example, placing an object in a container. In a strongly-typed language like C++, the programmer is forced to write a template, i.e. a class parameterized by type. Template programming can be cumbersome and tricky, and quickly leads to code bloat. Alternatively, more weakly-typed languages like Java allow collections of anonymous Objects, but these must be cast back and forth between the anonymous type and the real type. Sadly this doesn't protect you from any errors, if you put in an Integer and read out a String, you get an error. This is annoying when you consider that it was a string when you put it in there three lines earlier, and now you have to tell the compiler that it's a string coming back out just to call toUpperCase().
Categories
Cox's main concern was the maintainability of large code bases. Experience from the structured programming world had shown that one of the main ways to improve code was to break it down into smaller pieces. Objective C added the concept of Categories to help with this proccess.
A category collected method implementations into separate files. That way the programmer could place groups of related methods in its own "category" to make it more readable. For instance, one could create a "SpellChecking" category "on" the String object, collecting all of the methods related to spell checking into a single place.
That might not sound like anything new, but one key aspect of the implementation is that the methods were added to the class at runtime. That means that the programmer can add categories to existing classes without them knowing about it. If the system you are supplied with does not contain a spell checker in its String implementation, you just add it.
Combining categories with dynamic typing produces a synergy that results in tremendous flexibility that is largely unexpected in most programming systems. Consider Java: simply allowing String to have a checkSpelling method added isn't enough on it's own, because the rest of your program won't allow you to call that new method - all methods must be known at compile time as a side effect of strong typing. Instead you must use helper objects, special proxy classes, or use the terrible visitor pattern, all of which add to the complexity and uglyness of the implementation.
But the usefulness of categories goes further. Since any method can be "covered" by one in a category at runtime, you can in fact fix bugs in existing compiled binaries. Once you get used to having this, you can't live without it.
A number of other languages have attempted to add this feature in a variety of ways. TOM took the Objective-C system to its logical conclusion and allowed for the addition of variables as well. Other languages have instead used prototype oriented solutions, the most notable being Self.
Other features
Obj-C in fact included a laundry-list of features that are still being added to other languages, or simply don't exist at all. These led from Cox's (and later, NeXT's) realization that there is considerably more to programming than the language. The system has to be usable and flexible as a whole in order to work in a real-world setting.
- all libraries are dynamically linked. This meant that large Objective-C programs were in fact quite small, because the library was already on the machine. Common today perhaps, but this is from the early 1980s, remember.
- libraries can be supplied in multiple versions in a single file, and applications can choose to use a specific version (4.3.2), the latest version (which happens to be 5.2.1), or even the latest of a pariticular major relase (anything from 4.x). Versioning problems like this continue to haunt other systems to this day, including Java and COM
- code can be provided in multiple object formats for different platforms, which avoids the need for a virtual machine entirely. Typical multi-platform Objective-C programs are smaller than most single-platform programs on other systems.
- delegation is trivial. Simply add a category that changes the "second chance" method to forward the invocation to the delegate. Presto.
- remote invocation is trivial. Simply add a category that changes the "second chance" method to serialize the invocation and forward it off.
- swizzling allows for classes to change at runtime. Typically used for debugging (freed objects are swizzled into Zombies, who's only purpose is to report an error when someone calls them). swizzling was also used in EOF to create database faults
Advantages
Obj-C is a very "practical" language. It uses a thin runtime written in C that adds little to the size of the application. In contrast most OO systems of the era used large VM runtimes that took over the entire system. Programs written in Obj-C tended to be not much larger than the size of their code and that of the libraries (which often didn't have to be included in the distribution), in contrast to Smalltalk systems where you needed huge amounts of memory just to open a window.
Likewise the language was implemented on top of existing C compilers (first as a pre-processor, later as a gcc module) rather than as a new compiler. This allowed Obj-C to leverage the huge existing collection of C code, libraries, tools, and mindshare. You can easily wrap existing C libraries - even in object code libraries - in Obj-C wrappers to give them an OO style and more easily use them in your programs.
All of these practical changes lowered the barrier to entry, likely the biggest problem for the widespread acceptance of Smalltalk in the 1980s. In general Objective C can be summed up as offering much of the flexibility of the later Smalltalk systems, in a language that is deployed as easily as C.
Disadvantages
The first versions of Objective-C did not support garbage collection. At the time this was a matter of some debate and many people considered the long "dead times" when Smalltalk did collection to render the entire system unusable. Obj-C avoided that problem by not including this feature. However in retrospect this is a serious oversite. Although some 3rd party implementations have added this feature (most notably GNUStep), it remains outside the standard.
Another problem is that Obj-C does not include a namespace mechanism. Instead programmers are forced to add prefixes to their class names, a poor solution at best. Adding a namespace system would be simple and natural under Obj-C (where they map onto the libraries system quite cleanly) so it is somewhat surprising this hasn't happened.
Finally, since the language was based on C compilers, it remains highly dependant on a header file to work well. This is an added complexity that is no longer nessesary and thankfully missing from most modern languages like Java or C#.
See also: