Objects in Cocoa are very similar to objects in other languages such as C++ or Java. Their structure and syntax is very different though. While C++ and Java objects are essentially extensions (in syntax and organization) of the struct
in C, Cocoa's objects are implemented in a completely different way, with a completely different syntax.
In C++, you'd create a class using some code kind of like this:
class myClass
{
private:
int anInteger;
float aFloat;
public:
void someMethod(float f);
int someOtherMethod(int i, float f);
};
and you'd have a class called
myClass
with 2 private member variables and 2 public member functions, or methods.
If you wanted, you could define the member functions inside the class declaration itself, or you could define them outside the class like this:
void myClass::someMethod(float f)
{
aFloat = f;
}
This would define the
someMethod
method of
myClass
. Because you can have different return types and argument types, C++ allows you to have different methods with the same name, as long as their types are different. This is a convention that is not allowed in Objective-C, as we shall shortly see.
In Objective-C, objects come in two parts, an
interface
and an
implementation
. These look completely weird to run-of-the-mill C/C++ Programmers, so brace yourself. This is an equivalent object in Objective-C.
@interface myObject
{
@private
int anInteger;
float aFloat;
}
-(void) someMethod:(float) f;
-(int) someOtherMethod:(int) i andFloat: (float) f;
@end
Right. So, we covered a lot right there. An object's
interface
is defined between
@interface
and
@end
. The name of the object is immediately after the
@interface
. Member variables are can be marked
@public
,
@protected
, or
@private
, with
@protected
being the default protection.
After the member variables, we declare the methods. The syntax here is pretty weird too. First, the method is declared either instance-scoped or class-scoped. Class-scoped is like
static
in C++. To declare a method as instance-scoped, use a minus sign:
-
. To declare it as class-scoped, use a plus sign:
+
.
Following the scope of the method, the return type is specified in parenthesis. Next comes the method name. If the method takes no parameters, we tack on a semicolon, and we're done. If it does, we tack on a colon, then specify the data type in parenthesis, followed by the variable name. If we have multiple parameters, it gets even more interesting.
-(int) someOtherMethod:(int) i andFloat: (float) f;
uses two parameters. Instead of just having a list of arguments, Objective-C names them so that the user can keep track of what's going on. The
andFloat
part is doing just that. We don't strictly
need to specify this part. We could simply use
-(int) someOtherMethod:(int) i: (float) f;
to make it look more like C. However, the names are pretty helpful, so I'd recommend using them.
As you've probably guessed by now, the
@interface
is similar the the class declaration. Thus, we're on to the
@implementation
.
@implementation myObject
-(void) someMethod:(float) f
{
aFloat = f;
}
-(int) someOtherMethod:(int) i andFloat: (float) f
{
anInteger = i;
aFloat = f;
}
@end
Not so surprisingly now, the
@implementation
defines the methods using almost the exact same syntax. It's pretty straightforward.
Typically the
@interface
goes in a
.h
header file. The
@implementation
goes in a
.m
source file. You can put them all in the same source file though if you want.
Inheritance is fairly common in Objective-C as well. In fact, it's practically essential for get to actually use our objects. Almost all the objects we create will extend
NSObject
. To do this, our interface line will look like this:
@interface myObject: NSObject
. Pretty close to C++'s method. It gets more complicated than this though, but that's for a future entry.
So now that we have basic objects at our disposal, it's time to talk about some rules regarding objects. First, objects cannot be statically allocated. If you try to,
gcc
will complain with an error like this: "error: statically allocated instance of Objective-C class." This is one of the reasons why we will almost always extend NSObject. The NSObject gives us a couple methods to dynamically create our objects.
myObject *mo = [[myObject alloc] init];
is the typical way to allocate and initialize an object. The
alloc
method, as the name implies, allocates the necessary storage space, and
init
similarly initializes the object. This is in league with C++'s constructors.
Instead of
delete
, as we would use in C++ to free space used by an object, we use the
release
method, like this:
[mo release];
.
Before we continue, you've probably noticed that we call methods in a really different way. Instead of the expected
myObject->method(args);
syntax, we use
[object method ... args]
. To call a method with arguments from our object, it looks like this:
[mo someMethod: 3.1415926];
. You can probably guess how multiple parameters are handled, but here's another example just in case:
[mo someOtherMethod: 42 andFloat: 1.234];
.
So, to tie it all together into a working -- though useless -- example, here we go.
#import <Foundation/NSObject.h>
#import <stdio.h>
@interface myObject :NSObject
{
@private
int anInteger;
float aFloat;
}
-(void) someMethod:(float) f;
-(int) someOtherMethod:(int) i andFloat: (float) f;
@end
@implementation myObject
-(void) someMethod:(float) f
{
aFloat = f;
}
-(int) someOtherMethod:(int) i andFloat: (float) f
{
anInteger = i;
aFloat = f;
}
@end
int main(void)
{
myObject *mo = [[myObject alloc] init];
[mo someMethod: 3.1415926];
[mo someOtherMethod: 42 andFloat: 1.234];
[mo release];
return 0;
}
When compiling, be sure to use
-framework Cocoa
or else you'll get errors that are hard to understand. Like the following:
/usr/bin/ld: Undefined symbols:
.objc_class_name_NSObject
_objc_msgSend
collect2: ld returned 1 exit status
As an added bonus, you've been exposed to
#import
. You can safely assume that it's basically the same as
#include
-- in fact, you can often use them interchangeably -- except that
#import
makes sure to only include the file once without the
#ifndef HEADER_H
/
#define HEADER_H
/
#endif
stuff that litters the top and bottom C header files.
There you have it, the basics of Objective-C objects, and simple usage of Cocoa's framework.