There are two major varieties of Cocoa available. The first variety, possibly the more well known of the two, is the kind that you can use to make a nice warm cup of chocolate milk. While tasty, it’s hardly proper subject matter for an operating systems information site. The second variety is far more on-topic: a programming environment for Apple Mac OS X that is the modern evolution of of the original NeXTSTEP frameworks. That’s what I’m here to talk about today.
Before I go on, let me give you a brief background of my programming experience. Up until I really started using Cocoa, I was what you could call a bona fide dabbler. I dabbled in Basic for a long time, starting with Microsoft’s Basic interpreter for the Commodore 64, graduating to GWBasic and QBasic in MS-DOS, and ending up using Visual Basic under Windows. I dabbled in C for a while, but didn’t get too far because, frankly, I wanted to create cool little Windows productivity apps and, for that purpose, C, or even C++ at that time (mid-90’s), was a major headache for a simple programming hobbyist like myself. After a while, I dropped out of programming altogether, focusing instead on Web graphics and HTML development (as well as electronic music, but that’s a whole other story).
What brought me back into application development was my Web design business. I tried hard for a long time to ignore the inevitable: I couldn’t rely on building Web sites using static HTML files alone for much longer. The Web was just becoming too big and too sophisticated, and large sites were taking too long to create. So I started looking into Perl. It was easy enough to take existing, open-source Perl packages and mess around with them, but it didn’t take long for me to discover that it wasn’t what I was looking for. Then I found out about PHP, and I was thrilled. Now here was a language I could get behind, because it was super-easy to embed some bits of code into HTML files and include other bits of code and HTML into those files dynamically. So I really jumped onto the PHP bandwagon, and since then I’ve heavily customized several open-source content management systems as well as developed a simple online ordering system for my Celtic band web site.
Which brings me up to the turning point in my programming escapades. Around the time I started working with Perl and PHP, I bought my first Mac, a PowerBook G4. This was two years ago, right after the first version (10.0) of Mac OS X was released. I loved Mac OS X instantly, and I became a PC “switcher” before it was the cool thing to do. While exploring the innards of this strange new UNIX-based Mac OS, I discovered Cocoa. I was long been wishing that I could get back into real end-user desktop application development, but I didn’t want to use a “simple” environment such as RealBasic (the Mac’s answer to Visual Basic). Plus, I had grown quite fond of the C-style syntax of Perl and PHP. Reading up on Cocoa, I found out that it was an object-oriented framework with a clean and elegant design built using the Objective-C language, and that it had been the official development environment for the NeXTSTEP OS which Apple had purchased back in 1997. Bottom line: it was solid and robust and had been worked on for many years. It had proven itself as a viable method of rapid, modular application development, and Apple had deemed it worthy enough to make it the de-facto standard for next-generation development on the Mac. So I decided to bite the bullet and learn how to program in Cocoa, and thanks to Apple’s brilliant move of bundling best-of-breed development tools with the OS for free, I could build my own apps without having to pay a single cent.
Which brings us to the present day. Now you can see where I’m coming from as a programmer: someone with a decent amount of experience in lightweight RAD languages and Web scripting languages. Most Cocoa programming guides expect you to be an expert in C or C++ programming, which I most certainly am not, so it took me much longer to wrap my head around some of the more difficult language constructs of Objective-C than it might someone else. Now that I feel that I’m at least at a knowledgeable intermediate level with Cocoa, I want to present some of the basic concepts of the environment to other people interested in Mac OS X programming (or Linux/BSD if you use the open-source clone of Cocoa called GNUStep) in a way that makes it easier to understand for “newbies” and people with experience in only simple scripting languages. However, I’m assuming that you have at least some very basic knowledge of programming concepts such as variables, data types, functions/subroutines, statements, etc., since discussion of those topics is beyond the scope of this article.
To start off with, we have to remember that Objective-C is a language and Cocoa is a framework — i. e., a collection of objects and functions that provide all the basic building blocks necessary to create a fully-featured GUI-based (or command line based) application. While Cocoa is built using Objective-C, other languages such as Java (or even Perl or Python) can be used to build Cocoa apps. But Objective-C is the default, and in many ways, the preferred language to use.
Objective-C is a beautiful language. While it is a superset of C, which means anything you can do in C you can do in Objective-C, the reality is that the Cocoa frameworks eliminate the need to use many of the standard C data types and library functions. Cocoa provides powerful objects for storing and manipulating strings, arrays, hashes, and many other common data types, and also includes a number of useful structures such as points and rectangles for use in coding graphics routines. Cocoa objects take care of most of the hassles of memory management, leaving you to focus on the real task at hand: coding features. While you’re free to intermingle regular C code using standard data types and Objective-C code using Cocoa objects all you want, the preferred way to send and receive data from the GUI side of your application is through Cocoa data objects. The major exception to this is numbers: most Cocoa objects use standard C number types like int
, float
, and double
, because they’re so simple and easy to work with.
There are a number of features to be found in Objective-C that can’t be found in C++. In fact, Cocoa couldn’t have been designed the way it was if NeXT had chosen C++ for its foundation. Objective-C is built around two core concepts: dynamic typing and run-time messaging (which embodies the secondary concept of dynamic binding). These concepts are mainly what sets Objective-C apart from its competitors.
Dynamic typing works like this: in Objective-C, an object identifier is a variable of type id
. id
is defined as a C pointer to an object stored in memory. This object can be of any type, or as the proper term is, it can belong to any class. It could be a Cocoa string object, or it could be a MyBigHouse object that you’ve created yourself. (If you don’t know what an object or a class is, don’t worry, it will all be explained shortly.) Since it isn’t determined until run-time, you have the ability to inspect the object and ask the object what class it belongs to before doing something with it. In a statically-typed language such as C++, you don’t have this kind of flexibility, since a variable always has to be of a certain type, even if limited “late-binding” functionality is available (a C++ thing).
Now in languages such as Perl or PHP, you simply call an object method much as you would a regular function. Not so in Objective-C. In Objective-C, you use messages. Basically, you send a message to Object A saying “do this”, and it does it. Methods are declared in a somewhat similar fashion to C functions, they can use multiple arguments, and they can return a value just like functions. In that case, the message is “Object A: do this and that and this and that and then give me back a response”. The distinction between calling an object method directly and sending the object a message instead is subtle but important. For instance, you may not know what kind of object you’re working with until run-time (because of dynamic typing), so how could the compiler know what method should be called ahead of time? Rather, because you’re sending a message, the Objective-C run-time engine looks up the appropriate method of the object and calls it on behalf of your code, and then passes the return value back to you.
The really neat thing about this is that you can ask an object if it responds to a “selector” (which is a special kind of variable containing an identifier that is linked with a method name), and then “perform” the selector on the object if that method is supported. So you don’t even need to know what kind of object you’re working with, just as long you can send it the right kind of message. You can even “save” a message and then use it later on, which is extremely important for Cocoa’s implementation of cross-application/cross-computer data communication, called “distributed objects”.
The Cocoa framework, while being very well organized, is very large and complicated, so I’ll save a lengthy overview of it for Part 2 of this article. But I’d like to get you up to speed on some of the very basics of the Objective-C language. I’m not going to get much into all of the philosophy and design principles of object-oriented programming right now. For that, I heartily recommend you read Apple’s excellent online book The Objective-C Programming Language. To sum it up, objects are nifty. Objects allow for “user-oriented” program design. Instead of designing the program’s architecture based on some arbitrary code organization only you will understand, you can design it around the intended feature set of the application. For instance, you can create a Person object, subclass it (more on that later) to make a JaredWhite object, and send it a writeCocoaArticle message. You can then tell it to notify you when the article is done, and when you receive its notification message, you can then send it a sendCocoaArticletoOSNews message and receive a yes or a no to determine if the transmission was successful. Objects also make reusing code easy, since an object only handles a specific, obvious portion of your application code, and in many cases is general purpose rather than specialized.
Now let’s down and dirty and start looking at code. Objective-C messages look like this (remember, in C, every statement ends with a semi-colon):
[anObject doSomething];
This line of code is telling “anObject” to “doSomething”. Or, more specifically, anObject is the receiver of the message “doSomething”. All messages in Objective-C are always enclosed in square brackets. This looks very different from C or C++, but it’s a simple, easy-to-read format once you get used to it. doSomething is the name of a corresponding method in the object, and is implemented like this:
– (void)doSomething {
// some code
}
This method doesn’t return anything, so its return value is of the “no value” C date type void
. All the method’s code is contained within the braces, just like with a regular C function. The two forward slashes indicate that all the remaining text on the line is a comment, not code meant to be complied.
The minus sign before (void)
indicates that this method is an “instance” method. If it were a plus, it would indicate that it is a class method. In Objective-C, each object belongs to a class. A class is a “blueprint” for object instances, and is actually initialized as an object itself by the Objective-C runtime. You can send this class object messages, but the only methods available are class methods as mentioned above. Basically, you can create as many instances of a class as you like, but there’s only one class object initialized by the Objective-C run-time ever during the execution of your app (so you don’t have to worry about it). In fact, you use a class object to create an instance of an object. The most common line of code to accomplish that is:
MyKindOfObject *myObject = [[MyKindOfObject alloc] init];
This code looks complicated, but it’s really very simple. The bit before the equals (=) sign says that the myObject
pointer (remember, a pointer is a variable pointing to an object stored in memory, and you put a * before the variable name when you first “declare” it to indicate that) is going to be pointing to an object belonging to the MyKindOfObject
class. The bit after the equals sign is a group of nested messages. Basically the way it works is that you can send a message to the object returned by a message. So the object returned by [MyKindOfObject alloc]
is sent an init
message. The alloc
message calls the standard Cocoa alloc
class method (also called factory method, since class objects can also be called factory objects because of their use as object instance creators). If you had written it yourself, you would have written it like this:
+ (id)alloc
{
// code to allocate memory and return an uninitialized object
}
Compare that method to the doSomething
method above. This one has a plus sign, since it’s a class method and not an instance method, and it’s return value is an id
, which means that it is a pointer to the object that was just created (note that you never put a * before id
, because the fact that id
is a pointer is already part of the data type).
Now back to that earlier message above. Outside of the [MyKindOfObject alloc]
message, we see an [... init]
message. Because alloc
returns an uninitialized object instance, we have to send that object an init
message to initialize it. init
is a standard Cocoa instance method.
Once an object is initialized, it can be used for anything you like. Until then, it’s of no use to anyone. So remember, you first have to create an object by telling the class object to allocate the memory for a new object and return a pointer to that object, and then you have to tell that object to initialize itself. Although there are more ways to code that procedure besides the one I presented above (more on that next time), you should always keep this concept in mind.
Now you may be wondering something, and that is: where are all these “standard” Cocoa methods coming from? How is it that your custom objects can use them automatically? The answer is: inheritance, technically known as subclassing. Inheritance is one of the most important aspects of the object-oriented paradigm. The idea is that you start off with a single object class, called the base class or root class, and then every object ever created is a “subclass” of either that class, or any other class that is a subclass of that class. Many classes are subclasses of other classes which are in turn subclasses of another classes which are in turn subclasses, ad nauseam, going all the way back up to the base class.
In Cocoa, the base class is called NSObject
. Every object created by Apple, you, or third-parties are going to be subclasses (either directly or indirectly) of NSObject
. Again, going back to the above example. MyKindOfObject
is a direct subclass of NSObject
. You can also say that NSObject
is the superclass of MyKindOfObject
. The alloc
class method and the init
instance method are actually defined in NSObject
, not your own class. However, you can change this behavior if you wish, because you have the power to override any method inherited from the superclass in your own class. In other words, you could write your own init
method to ask another object for important information before completing the initialization process. In that case, your init
method would be called instead of the superclass’ init
method when another object sends your object an init
message. But here we come to a dilemma. NSObject
‘s init
method contains all kind of special code to deal with memory management and other low-level stuff. If you override it with your own method, that code won’t get run. What do you do? Thankfully, there’s an easy solution. Objective-C provides two special keywords: self
and super
. self
is a variable that points to the current object itself. super
is a keyword that finds the superclass of the object and then points to it. So, if you wanted to write your own init method, you could do this:
– (id)init
{
self = [super init];
// custom code goes here
return self;
}
Here, you’re getting the initialized object returned by the superclass’ init
method and assigning it to self
. self
must be returned at the end of the method, or your program will crash. But before you return self
, you can do anything you like, including creating other objects and setting up instance variables. Which brings me to my final point. Objects are made up of not only methods, but instance variables. Instance variables are variables you can define for a class that you can use to store data internally in the object. For example, a Person object could have an instance variable called fullName, and another one called hairColor. These instance variables could be standard C data types, custom data types, or other objects, just like regular variables. Bear in mind that, by default, instance variables are only available to the object that defines them, and this behavior should very rarely be altered. However, objects commonly allow their instance variables to be changed or retrieved though the use of accessor methods, which I’ll explain in Part 2 of this article. Also, an important thing to remember is that every object instance has its own collection of instance variables. So one Person object’s fullName variable could contain a “Joe Brown” string and another Person object’s fullName could contain a “Mary Smith” string. This type of functionality, along with object methods, is what in object-oriented parlance is called “encapsulation”. That is, the implementation of an object (its methods and instance variables) is hidden behind its interface (the messages you can send to it). This allows for modularity, code reuse, and a whole bunch of other cool things. You’ll love it.
That’s it for Part 1, and it was quite a workout. You learned how Cocoa and Objective-C fit together, what an object is and what a class is, how to send objects messages, what methods and instance variables are, how subclassing works, and more. Next time, in Part 2, you’ll learn how to program an object’s interface and implementation (a very simple operation), as well as how to create methods that support one or more arguments (input variables), and then we’ll start delving into the Cocoa framework itself. Until then, I just want to reinforce the idea that Cocoa programming is really fun. It’s easier that it looks, and you can build amazingly-sophisticated programs with comparatively little effort. While some concepts can be difficult to master, nothing is so complex that it can’t be easily explained. While waiting for Part 2, I suggest checking out the following Web sites:
Apple’s Cocoa Documentation
http://developer.apple.com/techpubs/macosx/Cocoa/CocoaTopics.html
Cocoa Dev Central
http://www.cocoadevcentral.com
CocoaDev (a simply wonderful user-contributed WikiWikiWeb site)
http://www.cocoadev.com
Mike Beam’s Programming With Cocoa column at MacDevCenter.com
http://www.macdevcenter.com/pub/ct/37
About the Author:
Jared White is President and Art Director of Web site and graphics design company GaelDesign. He is also Editor-in-Chief of The Idea Basket, an e-zine featuring provocative news commentary, articles, editorials, and reviews related to software and interface design, the Internet, multimedia, and technology. Jared became a PC-to-Mac switcher in 2001 and has been having a blast with Cocoa ever since. He can be reached via e-mail at [email protected].
I hope Apple or atleast the GCC dudes will drop this horrible “[obj method]” syntax – it makes a a source – especially when you mix it with arrays – unreadble. The ‘dot’ is the way to go – just like Java: obj.method.
Maybe its the reason for the missing code completion in PB.
Some more GNUstep tutorials can also be found here: http://wiki.gnustep.org . They apply to Cocoa most of the time.
It is much more complicated to have code completion when you have a dynamically typed language like Objective C. But code completion is much less useful in such a language, where there aren’t twenty variants of the same method, each differing for the arguments type.
Regarding message syntax, I find the Smalltalk syntax (which is the syntax ObjC uses for message) much clearer than the Java one, especially when you have many arguments.
I noticed alot of compersions to C++. It may be helpfull to point out the fact that C++ follows the simula 67 style of OO not that of smalltalk. Here is a link to a nice table comparing Objective-C, smalltalk-80, C++, and Eiffel:
http://www.dekorte.com/Objective-C/Comparisons.html
or Linux/BSD if you use the open-source clone of Cocoa called GNUStep
I strongly suggest Jared White read GNUstep’s “Our mission” ( http://www.gnustep.org/information/mission.html ) before he claims such a thing.
This is helpful; I’ve been trying to get into Cocoa (I’m quite acuanted with C/C++, perl, Basic (Of course), RealBASIC, and a bit of Java). I’ve hate C++, liked Basic but was fruturated with gotos and its limitations. RealBASIC was good but I was quickly limited with that, and java I could never wrap my brain around.
This was very helpful; even more helpful were the links. Using Cocoadev’s tutorials I’m already understanding Obj-C, and liking it. Thanks! =)
I hope Apple or atleast the GCC dudes will drop this horrible “[obj method]” syntax – it makes a a source – especially when you mix it with arrays – unreadble. The ‘dot’ is the way to go – just like Java: obj.method.
Maybe its the reason for the missing code completion in PB.
Used to be of this mind. Less certain now. I’m still not too keen on naming every argument. I used to have a big problem with lisp’s syntax too, and I’m over it. (Waaaaay over it.)
I don’t see why this would limit code completion in PB. If you have the pointer type of an obj you should be able to present reasonable code completion. (You could even detect for a Class/Interface test in a surrounding if statement and do some intelligent code completion.)
I’m hoping that code completion will make it into PB at WWDC. I really think that this feature would turbocharge application development. (I’m an emacs-with-viper-enabled kind of guy, but, having used Eclipse for the past six months has turned me around a bit.) The easier Apple makes it for newbies and middlin’-bies to wade in, the better.
Cheers,
prat
I actually started doing OO programming in Smalltalk which has a format simlar to objective-c (minus the [] messaging brackets). And when I switched to Java I really though its object.method() syntax was incredible ackward, expecially when it came to multiple parameters.
So I guess what I am saying here is give it a chance after all the C++/Java syntax grew on me.
Thanks for this article.
The Objective-C syntax is much better than C++ or Java syntax. I much preffer to write (and read) [myWindow nextEventMatchingMask:myMask untilDate:myDate inMode:myMode dequeue:YES] than myWindow.nextEventMatchingMask(myMask, myDate, myMode, YES). Patrick g, Ask the smalltalk comunity if they think the keyword syntax (adopted by Smalltalk and Objective-C) is unreadable.
Cocoa is by far the best application framework I’ve seen. And I love the fact that it can be used from so many scripting languages (see http://www.fscript.org/links.htm for a list).
Sorry, but, coming from the land of C/C++ and perl…
[obj method];
makes a lot more sense then…
obj.method
This is due to the fact in C/C++, and perl, I’ve become used to using brackets and parens for all of my groupings; this continues with this time-honored tradition, and it makes it easier to read when a obj-method begins and where one ends (Hint: follow the []s).
Should be:
obj.mehod;
Forgot the semi. =)
Hi Chris,
GNUstep’s mission page clearly states “GNUstep’s goal is to create a free, superior development environment based on and inspired by the OpenStep standard developed by NeXT Computer Inc. (now Apple Computer Inc.) and the OPENSTEP implementation of this standard.”
So, while GNUstep may not be a 100% clone of Cocoa as it stands today, it is (for all intents and purposes) a clone of the original OpenStep specification. The GNUstep project is adding some new classes to maintain compatibility with Cocoa, but there’s isn’t a 1:1 compatibility ratio. I realize that. On the other hand, while the GNUstep developers are certainly doing a fantastic job, that doesn’t mean we shouldn’t recognize the fact that GNUstep is basically just a copy of an original specification created by another organization.
Regards,
Jared
From what I’ve read, you can make a null pointer reference in Objective-C. It won’t kill your program. However, I’ve never been able to find out what the result is. Also do you have to give an object a type in Objective-C? Otherwise, how does the compiler know if you’re calling the correct method on an object? Why can’t you create an object on the stack? I’d have to agree with the camp that doesn’t like the square braces. That combined with naming arguments (although that’s not required) and Objective-C’s memory model makes a statement the equivalent of (Java vector add method):
v.addElement(new Integer(1));
hard to read.
I know it’s easy to get entrenched in coding in a very particular style, but the claim that having to use Objective-C’s square brakets is awkward or that Java’s syntax is confusing is just lame. Sorry but I guess that’s a bit of a flame…
Jason,
1) Message sends to null pointers are just ignored.
2) The compiler doesn’t need to know – the runtime figures it out.
3) Its just simpler that way. Objective-C objects are not meant to be thought of like C structs.
4) If you have a method with a lot of arguments, named parameters make things a lot easier, because there is no chance you are going to mix up the order. Its amazing how upset everyone gets over the weirdness of the square brackets initially. I did too, but you get to love them after a day or so, trust me!
your example would be something like
[v addExample:[Integer new:1]];
I don’t see how that is any harder to read.
better than Qt? =p
Messages to nil (or the Nil class) normally return nil (some runtimes allow this behavior to be easily modifed. This allows you set up a big chain of messages and only worry if the final result is nil:
foo = [[[[NSData alloc] initWithContentsOfFile: @”my.data”] autorelease] md5];
You don’t have to deal with types in ObjC the same way you’re think of. Every object *does* have a type/class it belongs to, but you need not worry yourself over the particulars to perform an operation. If you have a collection that responds to -addObject:, that is enough; why sweat over it being an array, set, linked list, whatever?
In some runtimes it *is* possible to create objects on the stack. That is not part of common systems, so clearly there is little benefit to it in the real world.
As far as syntax issues go, some of you people simply need more exposure. A professional programmer should be able to get beyond syntax issues relatively easily, and ObjC has the most minor of syntax differences from C. For your example, the equivalent Cocoa code would be:
[v addObject: [NSNumber numberWithInt: 1]];
Hardly a difficult read. Where the ObjC syntax really shines is with multiple arguments. Compare:
new Account(“Steve”, 50, 32, “Phil”)
with
[Account accountWithOwner: @”Steve” age: 50 startingBalance: 32 accountManager: @”Phil”]
I’d much rather come across the later in code I had to maintain.
>1) Message sends to null pointers are just ignored.
How then do you figure out if you’ve made such a programming error? I’ve seen such things happen in C++ in UNIX, but the consequences aren’t good and very hard to track down.
>2) The compiler doesn’t need to know – the runtime figures >it out.
What happens then if I manage to call a method on an object that doesn’t support it?
>3) Its just simpler that way. Objective-C objects are not >meant to be thought of like C structs.
Simpler for whom? Memory management is the number one cause of bugs in software. If you can’t put some objects on the stack, that’s more memory to manage (and thus more potential bugs). To be honest, I don’t know a whole hell of a lot about autoreleasepools or whatever they’re called, so that might solve some of this problem.
>4) If you have a method with a lot of arguments, named >parameters make things a lot easier, because there is no >chance you are going to mix up the order. Its amazing how >upset everyone gets over the weirdness of the square >brackets initially. I did too, but you get to love them >after a day or so, trust me!
>
>your example would be something like
>
>[v addExample:[Integer new:1]];
>
>I don’t see how that is any harder to read.
Well, I remembered the object initialization process for Objective-C requiring two methods, but I guess I’m wrong. As far as naming parameters being easier, not only do you have to remember their order, you also have to remember their name, unless you have a reference for the class you’re using, and then the point is moot.
How then do you figure out if you’ve made such a programming error? I’ve seen such things happen in C++ in UNIX, but the consequences aren’t good and very hard to track down.
Use NSAssert and check whether object is nil or not.
What happens then if I manage to call a method on an object that doesn’t support it?
You will/may get an exception that ‘instance of Foo does not respond to selector bar’ or similar.
To be honest, I don’t know a whole hell of a lot about autoreleasepools or whatever they’re called, so that might solve some of this problem.
It does. In ObjC you do not have to worry (too much) about garbage collection.
Well, I remembered the object initialization process for Objective-C requiring two methods, but I guess I’m wrong.
You can use
NSData *data = [[NSData alloc] init];
or
NSData *data = [NSData new];
Same thing, though the latter is considered bad style.
As far as naming parameters being easier, not only do you have to remember their order, you also have to remember their name, unless you have a reference for the class you’re using, and then the point is moot.
That is true, however, [foo containsObject: bar]; is easier to read and (well, not necessarily in this example) understand.
GNUstep’s mission page clearly states […]
GNUstep and Cocoa both are OPENSTEP implementations, plus, both bring along extensions to that specification.
GNUstep does indeed implement some of Cocoa’s extensions as well, but the primary focus is a direct OPENSTEP implementation. If it was to go after Cocoa, rest assured that Apple Legal will take a very close look at it…
So, bottom line is, you will be able to write applications using GNUstep and then port over to Cocoa – eg. as Ludovic Marcotte did with GNUMail ( http://www.collaboration-world.com/gnumail/ ) – but the other way round will be much harder to do.
To be precise, Cocoa is *not* an implementation of OpenStep. Cocoa is highly similar to, and is based on the OpenStep API, but not every OpenStep class or method is present in Cocoa, and there’s a great deal of Cocoa that was never in OpenStep.
-jcr
OK, I see what you all are saying. GNUstep is based on OpenStep, as is Cocoa, but both add on to that original spec in different ways, therefore, GNUstep is not a “clone” of Cocoa, but rather OpenStep. OK, that sounds logical. Since I’m not familiar with exactly what Cocoa has added to OpenStep, I didn’t realize the extent of the differences.
Thanks for the clarification.
Jared
While the true goal of GNUstep is to be an OpenStep implementation, it’s also right to say that quasi all the additional classes from Cocoa are implemented (with the minus of NSDrawer and NSToolbar — and yet some people seems to works a bit on them). In fact, the major problem when porting cocoa->gnustep is eventually the lack of ObjC++ (and of course of the proprietary frameworks also available on Mac (quicktime…) that could be used by an application). So imho, people should be aware of the different goals and possible differences, yes, but overall both platforms are quite compatible.
I’ve been looking to the GNUStep framework. I’ve done only a bit of C/C++ so it’s a bit harder for me. I hate having to write a bunch of code and weird macros Just to create a window with a few buttons (aka wxWindows/C++). Using Gorm I created a very simple “hello world” app and wrote very little code. Not only that, my app came with a menu bar and a working exit menu item! And if I drag the menu someplace, it shows up in the same place when I run it again! I didn’t write a single line of code to do such things! I like C++ and all, but I don’t want to get into wierd things such as virtual methods and such. When python bindings for GNUStep show up I’ll definately jump in. I can’t wait till part 2!
Openstep and Cocoa differ in that Cocoa is a superset of Openstep.
Cocoa has XML property lists (Openstep specifies textual, and I prefer it this way, or this behavior should be able to be toggled), some Web-enhanced methods, and some revised UI classes.
If you want other tutorials/presentation articles on GNUstep, you could also check the links I put on http://www.roard.com/docs/ …
If i recall, the creators of smalltalk orginaly envisaged a language which would be used to teach children how to program computers.
Hence the syntax was designed to be as logical and easy to read as possible, where C etc and C++ were designed by techies and committes looking for the quickest easiest way to achieve a particular task (hence all those stange little syntaxical anomilies which are so much fun to play with when you first learning the bloody things ….)
Well personnally I found the [] syntax quite elegant since the beginning … as it “feels” more like you send a message and not simply do a method call. And it let you send messages quasi- in the form of sentences (with the possibility of naming the arguments).
Frankly it’s so much better when you take the readibility of a program in count…
At the beginning I found also the OpenStep API quite “verbose”, with long names, etc. But in fact it’s not painful tu use (I adapted very quickly), perhaps because it’s easy to retain the method’s names … And the big, big advantage, is here again the readibility of the code. That’s one of the big plus with ObjC/OpenStep programs …
(to the one asking for a comparison between Qt and OpenStep, in my opinion, OpenStep is better. More coherent. But Qt is a also a wonderful toolkit — that’s what I used before committing to GNUstep and Objective-C 😉 futhermore, the Signal/Slot Qt thing is similar to Objective-C . Only that with Objective-C, it the normal method 😉
“As far as naming parameters being easier, not only do you have to remember their order, you also have to remember their name, unless you have a reference for the class you’re using, and then the point is moot.”
Cocoa methods are named very consistently — you can often just guess at the method name you want to use w/o consulting the documentation.
The main benefit with named arguments is not in recalling method names, but in reading source code. If you are not familiar with a piece of code (or you are revisiting your own code after a long hiatus), a line like
[shape drawAtXCoord:2 yCoord:7 width:5 height:10 bordered:YES];
is a lot easier to decipher than the more Java-like
shape.draw(2,7,5,10,true);
I wish more languages provided named arguments. The only ones I know of are Smalltalk and Objective-C. Any others out there?
Thanks for the article. Now I can truly understand why (with respect to ObjC and Cocoa) C++ is more commonly used than ObjectiveC. At first glance, GTK+ and KDE libs are much more simple than cocoa. More clearly defined functions and less code. Also, C/C++ is much more optimised than ObjC.
Mabye some of the “readability” issues revolve around style? For example, I find
[shaped drawAtXCoord: 2
yCoord: 7
width: 5
height: 10
bordered: YES];
much more readable than the original example.
I do agree that Objective-C’s style lends itself much better to maintaining code, but the differences between a function call and sending a message to an object can lead to ugly syntax.
Is their a cost associated with all this runtime checking in objective-c ?
Well, you can use comments to document code in other languages, which makes the point of named arguments rather moot.
Sure, a lot of people don’t bother commenting, and you may argue that its more of a hassle to do than named arguments, however I find it a good practice, as it will also make your code easily readable, in any language.
Well, you can use comments to document code in other languages, which makes the point of named arguments rather moot.
Sure, a lot of people don’t bother commenting
Which is exactly the point. It’s better to force someone to make more readable code than to let them not. Remember: A True Klingon Warrier Doesn’t Comment his Code. Or whatever the quote is.
As a long time Smalltalk (20+ years) and NeXT/OpenStep (12+ years) user/developer, who currently uses BOTH systems, I find that they each have their advantages and attractions. Certainly Smalltalk code is easier to read and just as certainly the OpenStep GUI is amazing (Win95 was cloned/devolved from it).
Objective-C is an excellent language with it’s well known merging of C and a variant of Smalltalk syntax, however since it lacks true automatic memory management I find my programming style must change significantly to take this into account. While programming in Smalltalk one can simply forget about memory issue, for the most part. This definitly affects style, effort, complexity and other factors in developing software.
The real pleasure of Objective-C on the OpenStep platform is the library of objects in the Application Kit Framework. These are simply designed very well and pack a mean punch. The compact size and potent density of the frameworks are comprehensible to most programmers thus they are very usable. One can write very powerful applications with it, as evidenced by the many awesome NeXT/OpenStep/Coca applications that have been written.
Any language with full automatic memory management has it’s advantages over those without. In this regards Java joins Smalltalk, Lisp and others in being “better” than C, C++ and Objective-C.
Languages that make the name of “parameters” in a method part of the method name seem to make the programs much easier to read. This is especially important for large teams. Smalltalk and Objective-C programs are amoung the easiest to read as they have “literate programming” principles built in.
It’s also important to have access to the source code or documentation via “browsing” tools while reading the source code of large and unfamilar systems. This is even more important for langauges like C++, C, Java, etc.. where the function names are not so readable
The differences in the lanuages and their supporting libraries make a difference, including a significant difference, in the outcome and the path taken to get there.
I for one, prefer languages like Smalltalk, where the syntax is as easy to write as it is to read. While I can program in lanaguages like Java, C++, Perl, Python, Objective-C, C, Assembly Language, etc, they are much harder due to their “syntax”.
It really depends on what you are trying to accomplish. The technicial success of the Objective-C based OpenStep/Coca applications and systems shows how even a few of the principles of Smalltalk can have a huge impact upon the outcome.
The libraries of objects in the many dialects of Smalltalk have variation and have evolved to meet the needs of the various their target markets. Smalltalk and it’s libary of objects, while powerful, aren’t perfect, which tool is?
The GNUStep effort offers a complelling opportunity with the merging of Smalltalk within the OpenStep standard. Good looks with a good language. It’s worth tracking, using and contributing to.
There are features of languages that can make significant differences in readablity, ease of use, performance, cost, maintainablity and overall results. I’m most interested in and my choices motivated by the features of languages that take over some of the burden from programmers (and shift it to the machine leading to a reduction in cost of development and overall development time). This is the purpose of progress after all, isn’t it?
There are tradeoffs with each language feature. For example, automatic memory management makes a huge difference in productivity with a tiny cost in run time performance.
Un-typed data/objects, as in Smalltalk, make a huge improvement in productivity. Some “every data item must be typed” aderants are concerned about run-time bugs. In practice, bugs occuring in untyped systems have more to do with the “architecture” and “design” than with the “untyped” characteristic. There are some situations where having types is important and it may well be that a typed language is better suited to the task.
Regardless of which language you use it’s obvious that architecture and design of the supporting object, data and code libraries playes a significant difference.
The success of the architecture and design of OpenStep reveals this. While Smalltalk is a better language and it’s core object library beats OpenStep’s/Coca’s hands down, OpenStep has an excellent feather weight Application Framework that goes a long way towards success. NeXT put their design attention on what people SEE after all!
The bottom line is computer languages are tools and tool selection for any particular job is an important aspect in many, but not all, projects. There is more than one road to Rome, after all. The tower of babel is the reality in the landscape of computer languages. Interoperation systems such as XML are paving a way for systems created in most, if not all, languages to be able to communicate. At last applications and systems developers are freed from many of the constraints placed upon them by others who prefer different choices. Overall architecture and design influence systems as much as – if not more than – which language you happen to choose to utter the prgram in.
May you choose your tools well for the task at hand, which by the way includes the choice of language for building operating systems. The language of choice for the operating systems project that I’m working on is a language that is evolving from Smalltalk and Assembly languages and advanced application frameworks such as OpenStep. There are enough cpu cycles now to raise the importance of architecture and design above that of simple raw performance. The computer age has just begun and the future is wide open for the systems of your dreams.
Which is exactly the point. It’s better to force someone to make more readable code than to let them not. Remember: A True Klingon Warrier Doesn’t Comment his Code. Or whatever the quote is.
This is crazy talk. I almost always prefer when languages stay away from hard and fast rules. An example of the difference between python and java. In java there are rules that aren’t there for technical reasons, but just to keep you in line. Whereas in python they allow you to break typical object oriented rules if you please. This allows you do take a “shortcut” if you want or need to.
It is like in certain classes where I program C professors will say “No global variables.” Not that a global variable causes problems, but they see it as a shortcut because it breaks certain programming models. I see it as the most efficient way to get the job done at times.
With so many comments on ObjC already, I doubt this post will be read by many, but I gotta say it anyway.
Going from C/C++/Java to ObjC, I found ObjC’s syntax very strange initially. But it only took me a while to get used to it, and now I find it absolutely beautiful.
With C++, I hated it in the beginning. And I hated it more everyday when I was working full-time using it.
On to Cocoa … again once I got passed the initial learning curve, it is incredibly elegant and intuitive.
Now if only Apple had release Yellow Box … 😐
Yes, I totally agree!
I have a long programming history. I started programming in the early eighties (I was 14 then) with line-numbered Basic on a Commodore PET, followed by Pascal and C/C++ during University.
At work I have used Cobol, Visual Basic and for the last two years JAVA. I am a Mac owner for 1.5 years now so I came in contact with Objective-C and I agree to Jay’s post:
Once you got passed the initial learning curve, Objective-C & Cocoa is incredibly elegant and intuitive.
It is like in certain classes where I program C professors will say “No global variables.” Not that a global variable causes problems, but they see it as a shortcut because it breaks certain programming models. I see it as the most efficient way to get the job done at times.If you’d ever worked on a large project with a programmer who held that opinion.. well you’d know its simply not true. I’d like tutors to be able to give people a smack around the ear if they spot a global variable.
Sorry, but I do find the [] syntax confusing, as it’s never clear what is the method and what are the arguments.
To claim that named arguments are easier to read may have some merit, but I’d note that most scripting languages let you do this (python does) and in languages like Java/C++/Delphi it’s less important anyway because in a good IDE you can hover the mouse over a method call to see the prototype anyway.
I’ve not seen anybody mentioned the big disadvantage of Objective-C, in that it’s very slow. There’s a reason languages like C, C++, Delphi etc work the way they do, and that’s because static typing:
a) Lets you catch some errors you otherwise would miss and
b) is very fast.
To be honest, I don’t see what advantages ObjC has over Python except perhaps the ability to use C code more easily. They both support OO, late binding, but Python has the advantages of a non-confusing syntax and true garbage collection.
@Eric Wang:
“I wish more languages provided named arguments. The only ones I know of are Smalltalk and Objective-C. Any others out there?”
Python offers *optional* named arguments. That is, you can use either positional arguments or named arguments.
They’re very useful for PyGtk, as most of the arguments have default values, using named arguments provides you with a way to specify only the properties you want to be different.
But in any way it’s used to improve readability, it’s just to improve efficiency of coding ;-).
Optional named arguments are also provided by OCaml and Ada95.
As with Python, they are particularly useful when you have default values.
In OCaml, there is the additional benefit that you can perform a partial application specifying parameters other than the first one. A brief explanation – given an f : ‘a -> ‘b -> ‘c, you can only do f x to get a function ‘b -> ‘c, but with f : x:’a -> y:’b -> ‘c you can say f ~y:y to get a function x:’a -> ‘c . Obviously, you could always use (fun y -> f x y) but the shorthand is convenient. In simpler terms, if you apply a function without giving all the arguments, the result is a function taking the remaining arguments. Without named arguments you can only give arguments in order.
Sorry, but I do find the [] syntax confusing, as it’s never clear what is the method and what are the arguments.
Well in the beginning I had difficulties too, I didn’t “got it”. In fact, it’s really simple :
[myObject messageWithArgument1: foo andArgument2: bar];
the function’s name (function signature, or selector) is NOT
messageWithArgument1:
as you could think, but :
messageWithArgument1:andArgument2: !
In fact, you put your arguments “inside” the method’s name/call … it’s not simply that you “name” the argument, the “argument’s name” is part of the method’s name.
I’ve not seen anybody mentioned the big disadvantage of Objective-C, in that it’s very slow.
It’s not “very slow”. It’s a compiled language, and frankly I don’t see the difference when programming with GNUstep or with Qt. I “know” that methods invocations are a bit slower due to indirection, but it’s barely noticeable. I think that today’s computer are too fast 😉 (and remember, NeXT ran on 68030, and their eventual slowness was mostly due to DisplayPostscript, not ObjC). Anyway, the biggest problem due to rapidity in a program is generally due to a bad algorithm/architecture rather than the language itself.
And of course, if you want, it’s trivial to “cache” the method call, thus no more indirection, it’s as fast a standard C function call !
You could easily use directly C if you care so much (never had the need to do that in fact).
Python has the advantages of a non-confusing syntax and true garbage collection.
Personnally I can’t stand the tab thing with Python… 😉
But what’s your thing with garbage collection ? With GNUstep, you are free to use a real garbage collector instead of retain/release ! (Mac OS X can’t, yes, but it’s available on GNUstep).
But strangely, retain/release/autorelease is more used anyway (I think that’s because it’s quite simple mechanism, efficient, and far painless than C memory handling, and not very complicate).
in perl you can pass everything as anonymous hashes…
which approximates named arguments 😉
For what it’s worth, I’m writing a signal processing app for some of my robot work (it’s a test suite for a c++ library to smooth out “warbly” sensor input, the warbles being spikes and pits resultant from the power source being used for multiple mechanisms, like servos, serial IO, etc etc).
So, since I’m developing on mac os x, in std c++ — what I do is write all my code as libraries, and then I write cocoa guis and objective c++ lib wrappers so I can test the mechanisms. It sounds like a pain, but really it’s not so bad. It’s kind of fun, actually.
Anyway, last night, in *TWO* hours only, I was able to write an app, entirely in objective c, which generates an abitrary number of fake sensor inputs, plots them along a graph with subpixel precision (go quartz!), and maintains a fast searchable “history” of values. At the moment I haven’t started writing my signal processing stuff (because I only started last night) but the point is, now I have a fully GUI noise generator of sorts which I can attach my c++ library to to test the cleaning algorithms.
Anyway, this isn’t a complex piece of code, but the fact is, I wrote it in two hours only, and when running it takes up less than 5% cpu — complete with the antialiased plotting of multiple inputs.
http://home.earthlink.net/~zakariya/files/Smoother.png
Frankly, if objective c is supposed to be slow, I don’t believe it. It runs beautifully, and it’s quite legible. I’m not going to convert, since really I’m a c++ guy, but frankly, I think I’ll be writing my GUIs in onbjective c from now on. The right language for the right task, right?
Right.
There is no, one, object-oriented programming language for the masses. I’m learning C++ right now because I want to contribute to KDE. If I wanted to contribute to Gnome, i’d probably learn objective C or pure C. Use the tool that’s right for the job.
Isn’t cocoa the leaf used to make cocaine?
What is a good book to get started on cocoa (the language)?
Try checking out http://www.cocoadev.com/
They’ve got a list of (all) Cocoa books along with (user) reviews.
Also, look at http://osx.hyperjeff.net/reference/CocoaArticles.php for a big list of articles on Cocoa.
I asked a friend who has never programmed in his life to choose between three forms of writing something:
[circle drawX:0 Y:0 R:2]
circle.draw(0,0,2)
circle.draw(x=0,y=0,r=2)
He picked the third. He said that the top was too complicated.
That’s like a doctor asking someone who’s not in medicine, “Which pill do you think would work better for lowering cholestrol? The white round one or the red capsule?”
The answer is worth exactly nothing.
Except for the fact that Smalltalk syntax was designed to be very easy. If he found it more confusing then the other options, possibly there is something there.
Over the last three years, I’ve taught Cocoa to I think between two and three hundred engineers. Most have had a C/C++ background. Initially, most view the square-bracket syntax as, at best, “odd”. By the end of a week, most seem either to like it, or at worst give it (albeit occasionally grudging) respect. Long-term experience shows that the “named arguments” style leads to more-readable, more-easily maintanable code. To those for whom this is the first exposure to the syntax I’d say, “Try it for a while before you rant.”
Regarding other aspects of the environment:
One could perhaps summarise Objective-C as being behaviour- rather than type-oriented. Those steeped in a long C++/Java tradition typically find the idea of not knowing what “type” an object is discomfiting. Experienced Objective-C developers are quite relaxed with the idea of just sending a message to an object, and expecting that the Right Thing will happen. The wide variety of Cocoa applications running reliably on users’ desktops suggests that the Objective-C developers’ attitude is justified…
As for memory management, this is another area which newcomers, and especially those who haven’t written a line of code yet, think will be difficult. Typically the difficulties are of their own making. The strategy implemented in Cocoa is consistent, reliable, and simple. It’s a shame Mr. White didn’t see fit to link to the longest-running Cocoa-oriented website, since it includes a number of articles on the subject of memory management:
http://www.stepwise.com/StartingPoint/Cocoa.html
Those who persist in “not getting it” are, in my experience, typically those who are least willing to “let go” of their C++/Java experience and work with, rather than against, the system. Please note, this is an observation, not a value judgment. In a similar vein, I am sympathetic to those who would like the “freedom” that garbage collection offers, however I wonder how many of those who demand it have looked in detail at the full range of reference types in Java. And have considered the effect of a full garbage sweep in a video-editing application as the user is fine-tuning sound-track placement. Most developers quickly get used to the memory management system, and grow to appreciate the additional control that it gives them over their application’s resource requirements.
Finally, regarding speed. There are two aspects to this:
(a) Recall that this is an environment that originally ran more than adequately on 68040-based systems with 16MB RAM (some might also say that the 68030-based systems ran fine with 8MB RAM, but I’ll stay in easily-defensible territory). The overhead of a method lookup over a function call is minimal (I think it was estimated by someone once at around 10% — note that there’s a lot of caching). If that has a significant impact on your application’s performance, I’d suggest that either it doesn’t do very much, or it’s badly architected.
(b) The slowest-running application is one that hasn’t been deployed yet. 15 years on, Cocoa still seems to be the best RAD tool in existence. And better than just a RAD tool, you can take your first attempt and develop it into an industrial-strength application. This is in part due to the flexibility Objective-C offers…
mmalc
The ordering of the parameters is not arbitrary. [object method: 1 With: 2 And: 3]; will call a different method than [object method: 1 And: 2 With: 3];. The parameters have no names, it’s just the name of the method that has been “spread out”. If you look at the name of the selector you will see that it will be method:With:And: in the first case and method:And:With: in the second case. This would be no different than having a C++ method called methodWithAnd and have the same “ability” to tell the intent of the parameters.
Oh and mmalc, garbage collectors have proven to be at least as effective as manual memory management and often even better. With todays powerful computers there is really no reason NOT to use garbage collection.
Oh I don’t know if syntax is the biggest worry for a newbie.
Wrapping one’s mind around all the concepts is hard[1]. Once you got that, syntax is realitively easy.
[1] Especially a mind already ingrained by another method.