Objective C adds Smalltalk style messaging on top of C. You don't need an Apple Mac to start writing Objective C, on Ubuntu you can just run the following to get all the edpendencies
sudo apt-get install gobjc gnustep gnustep-make gnustep-common
I think that's the right list - those short of disk space could probably find a more minimal set! If you get crazy errors like this:
/usr/share/GNUstep/Makefiles/GNUstep.sh:288: no such file or directory:
/usr/share/GNUstep/Makefiles/print_unique_pathlist.sh
Make sure that your shell start up script (.bashrc or .zshrc) has
#GNUSTEP Environment vars
. /usr/share/GNUstep/Makefiles/GNUstep.sh
Hopefully that's a more condensed version of the tortuous path I went through to get things installed... Back to the interesting bits.
The hello world program is exactly the same as for C. By convention ObjectiveC programs use the ".m" extension (for method). You can compile this by simply doing
gcc helloworld.m
#include <stdio.h>
int main(int n, char** argv) {
printf("Hello world\n");
return 0;
}
Obviously that's not very interesting. Header files are declared in a
.h
file and take the following form. - An
@interface
declaration simply states the data of the object, following that there are a number of method declarations. +
indicates a class level message (e.g. a static)-
indicates an instance method.NSObject
is the object we inherit from
NSString
is the interface for immutable strings, similar to std::string
or java.lang.String
. I created hello.h
.
#import <Foundation/Foundation.h>
@interface Hello : NSObject{
NSString* name;
}
+ (NSString*) details;
- (NSString*) name;
- (void) setName : (NSString*)newName;
@end
Implementation files follow a similar pattern,
hello.m
looks like this. retain/release are messages on the base object which control when an object goes out of scope by using reference counting. I'm sure there's much more to it than that, but I found these simple rules explained what I needed to get going without much hassle.
#include "hello.h"
@implementation Hello
+ (NSString*) details {
return @"This is a string.";
}
- (NSString*) name {
return name;
}
- (void) setName: (NSString*)newName {
[name release];
name = [newName retain];
}
We can use this object in the main file (
helloworld.m
). The first line initializes a pool because some of the NSString
constructors return autoreleased objects. Sending messages to objects uses the [] syntax. The example below shows a static method call (send a message to the class object itself) and a method call (send the message to the instance).
#include "hello.h"
int main(int n, const char* argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString* s = [Hello details];
printf("Result from a static call: %s\n", [s UTF8String]);
Hello* hello = [[Hello alloc] init];
printf("Name is not initialized: %s\n", [[hello name] UTF8String]);
[hello setName: @"Jeff"];
printf("Your name is %s\n", [[hello name] UTF8String]);
return 0;
}
Building this requires a makefile, following the instructions in the tutorial I created
GNUmakefile
with the following:
include $(GNUSTEP_MAKEFILES)/common.make
APP_NAME = Hello
Hello_OBJC_FILES = hello.m helloworld.m
include $(GNUSTEP_MAKEFILES)/application.make
Which when build gives me an executable in
./Hello.app/Hello
:
Result from a static call: This is a string.
Name is not initialized: (null)
Your name is Jeff
Hurrah, my first ObjectiveC app... Now it's only a small matter of time before I become rich on the app store and can retire! Or not :)