Introduction
Contents
What is Objective-C?
Objective-C is an object oriented computer programming language. It is
a superset of ANSI C and provides classes and message passing similar to
Smalltalk.
Objective-C includes, when compared to C, a few more keywords and
constructs, a short description of which follows. For a comlete example
of the application of the constructs, see part 3 of this FAQ.
Syntax
@interface declares a new class. It indicates the name of the class,
the name of its superclass, the protocols adhered to
( See Protocols ),
the layout of the instance variables
(similar to the definition of a struct, but including encapsulation information
( See Encapsulation ))
and declares the methods implemented by this class. A class' interface usually resides
in a file called `classname.h'.
@implementation defines a class. The implementation is no more than a
collection of method definitions. Without an implementation, a class
does not exist at run time. The implementation of a class usually
resides in a file called `classname.m'.
A @category is a named collection of method definitions which are
added to an existing class. A category is not allowed to redefine a
class' existing methods.
Objective-C includes the predefined type `id' which stands for a pointer
to some object. Thus, `id obj;' declares a pointer to an object. The
actual class of the object being pointed to is almost irrelevant, since
Objective-C does run-time type checking.
- message; declares a method called `message'. The `-' indicates that
the message can be sent to objects. A `+' instead indicates the message
can be sent to class objects. A method is similar to a function in that
it has arguments and a return value. The default return type is `id'.
If a method has nothing useful to return, it returns `self', which is a
pointer to the object to which the message was sent (similar to `this'
in C++).
- [obj message];
- [obj message: arg1];
- [obj message: arg1 with: arg2];
are examples of sending a message to the object OBJ with 0, 1 and 2
arguments respectively. The name of the message is called the selector.
In this example, the selectors are: `message', `message:' and
`message:with:', respectively.
See Sample Code .
Differences with C++
Dynamic vs. Static
C++ follows the Simula 67 school of OO programming, where Objective-C
follows the Smalltalk school.
In C++ the static type of an object
determine whether you can send it a message, in Objective-C the dynamic
type determine it. The Simula 67 school is safer, in that more errors
are detected at compile time. The Smalltalk school is more flexible, as
some valid programs will execute correctly in Smalltalk, where they
would be rejected by Simula 67.
Stepstone's Objective-C allows you to chose between the dynamic and
static binding, GNU and NeXT do not. ANSI C++ allows you to use dynamic
binding, but discourages you from doing so.
In many ways, the difference between C++ and Objective-C is more a
question of mindset than technical barriers. Are you willing to offer
some flexibility for some safety? Advocates for the Simula 67 school
claims that a well designed program doesn't need the extra flexibility
(a lie), while advocates for the Smalltalk school claims that the errors
are no problem in practice (another lie).
Pragmatic differences with C++ include:
- C++ has operator overloading
- Whether the usefullness of operator overloading is greater than it's problems
is not agreed upon. But it is cleat that it is a not an OO related feature.
- C++ has multiple inheritance
- The merits of multiple inheritance are also debatable.
In any case, There are several ways to `get around' this in Objective-C (see below).
- The added syntax and semantics of C++ is huge,
- while Objective-C is C plus just a small number of new features all of which are
related to adding OO features.
Similarities to Smalltalk
What exactly is it that makes Objective-C have `classes similar to
Smalltalk', and what are the resulting capabilities of Objective-C?
Objective-C is as close to Smalltalk as a compiled language
allows. The following is a list of the features `taken' from Smalltalk:
Compiling
- Objective-C is compiled ---Smalltalk is only partially compiled. The
current Objective-C implementations are all much faster than any
Smalltalk. For example ParcPlace Smalltalk-80/4 is at least 3 times
slower than both the GNU and NeXT Objective-C's. (This was measured
using the Self/Smalltalk benchmark suite available by FTP from:
`self.stanford.edu:pub/Self-2.0.1' .)
- Objective-C does hybrid typing :
one can choose to represent a string as a `char *' or as an object,
whereas in Smalltalk, everything is an object. This is a reason for
Objective-C being faster. On the other hand, if every bit of
information in an Objective-C program would be represented by an
object, the program would probably run at a speed comparable to
Smalltalk and it would suffer from not having optimizations
performed on the basic classes, like Smalltalk can do.
Messages
- You may add or delete methods and classes at runtime. (On GNU and
NeXT one can load new classes and categories. On Stepstone, which
lacks categories, the only way to add methods is to load a subclass
which then does a ` +poseAs: ' of the class to have methods added.
This is less flexible, but it sort-of does the trick of just adding
methods.)
- Much of the syntax, i.e. Smalltalk uses method names like
` a:method:name:', as does Objective-C. In Objective-C, the message
sending construct is enclosed in square brackets, like this:
` [anObject aMessage: arg]' whereas Smalltalk uses something like
` anObject aMessage: arg'.
- The basic class hierarchy, that is, having class `Object' in the very
top, and letting most other classes inherit from it.
- Most method names in class object is the same. E.g. `respondsTo:'.
What is called
- `doesNotUnderstand:' in Smalltalk is called
- `doesNotRecognize:' in Objective-C.
Forwarding
- Smalltalk normally uses `doesNotUnderstand:' to implement
forwarding, delegation, proxies etc. In Objective-C, these tasks
are different:
- forwarding/delegation: `forward::' can be overridden to
implement forwarding. On the NeXT, `forward::' is even used
when passing to super.
- proxies: (Next) An instance of the NXProxy class forwards all
methods and their arguments to the remote object via Mach
messages.
Classes
- Objective-C has meta classes mostly like Smalltalk.
- Objective-C does not have class variables like Smalltalk, but pool
variables and globals are easily emulated via static variables.
Nice Features
- The possibility to load class definitions and method definitions
(which extend a class) at run time.
- Objects are dynamically typed: Full type information (name and type
information of methods and instance variables and type information
of method arguments) is available at run time. A prime example of
application of this feature is `-loadNibSection:owner:' method of
NEXTSTEP's Application class.
- Persistence [...].
- Remote objects [...].
- Delegation and target/action protocols [...].
Common problems
What are some of the common problems of the language
and how can I work around them?
Multiple inheritance
- There is no innate multiple inheritance (of course some see this as a benefit).
- To get around it you can create a compound class, i.e. a class
with instance variables that are ids of other objects.
Instances can specifically redirect messages to any combination
of the objects they are compounded of. (It isn't that much of
a hassle and you have direct control over the inheritance
logistics.) [Of course, this is not `getting around the problem
of not having multiple inheritance', but just modeling your
world slightly different in such a way that you don't need
multiple inheritance.]
- Protocols address the absence of multiple inheritance (MI) to
some extent: Technically, protocols are equivalent to MI for
purely "abstract" classes (see the answer on `Protocols' below).
- [How does Delegation fit in here? Delegation is extending a
class' functionality in a way anticipated by the designer of
that class, without the need for subclassing. One can, of
course, be the delegate of several objects of different
classes. ]
No class variables
- You can get around this by defining a static variable in the
implementation file, and defining access methods for it. This
is actually a more desirable way of designing a class hierarchy,
because subclasses shouldn't access superclass storage (this
would cause the subclass to break if the superclass was
reimplemented), and allows the subclass to override the storage
(if the classes access all their own variables via methods).
- [The question remains what the exact syntax of class variables
should be: Should a class object A be seen as an instance of its
meta-class MA, which has a super class MB being the meta-class
of A's super, B, and, as such, should A have seperate instances
of class variables defined for B? Or not?]
Different return types for methods with the same name
If two different classes both happen to have a method of the same name,
and the return type of the methods differ, you get a warning from the
compiler when it comes to the use of that method in your code, and one
of the method types is chosen over the other.
To avoid compiler warnings, you need to either:
- Cast the receiving objects appropriately
- Statically declare them
So, if you have:
@interface MyClass : Object
{
int number;
}
- (int)number;
@end
and
@interface OtherClass : Object
{
double number;
}
- (double)number;
@end
Your method can be either:
- aMethod
{
id MyClass = [[MyClass alloc] init];
id OtherClass = [[OtherClass alloc] init];
int myNumber = [(MyClass *)MyClass number];
double otherNumber = [(OtherClass *)OtherClass number];
return self;
}
or:
- aMethod
{
MyClass *MyClass = [[MyClass alloc] init];
OtherClass *OtherClass = [[OtherClass alloc] init];
int myNumber = [MyClass number];
double otherNumber = [OtherClass number];
return self;
}
dekorte@symnet.net