Apr 97 Getting Started
Volume Number: 13
Issue Number: 4
Column Tag: Getting Started
A First Look at Objective-C
By Dave Mark, ©1997, All Rights Reserved. http://www.spiderworks.com
Well, it finally happened. Apple made their OS decision, catching many of us by
surprise. Personally, I am very excited by Apple's move. As was clear from the energy
at Macworld Expo, things are finally moving. Apple has made a bold move. Now we have
to retool and rethink our programming strategies.
As Apple made clear, the System 7.5 version of the Mac Toolbox still has some
significant legs and will likely be part of our lives for some time to come. As I write
this, the announced release schedule for Rhapsody (code name for the new OS) does not
show a significant beta in our hands until January of next year. Nothing to complain
about there. Of course, it will take time for Apple to marry their technology to that of
NeXT and we all want this job done right.
My point is that there are some important decisions we all have to make, but the
current schedule gives us the luxury of continuing down the current path (System 7.5
apps) without penalty, while giving us the time to plan for the new order.
What About Be?
Before we move on to the main focus of this column, I'd like to take a second to talk
about the apparent loser in the OS wars: Be, Inc. You might think that because Be was
not able to work out a deal with Apple, they have become damaged goods. Not so! As
anyone who attended the first ever Be developer's conference will tell you, the BeOS is
cool, the commitment from developers is there, and there's an excitement in the air, a
feeling of being in on the ground floor of something big.
Bottom line, we now have two technological evolutions to follow. Things are about to get
very interesting.
Java, C, C++, and Pascal vs. Objective-C
There are a number of questions raised by Apple's acquisition of NeXT. (See this
month's Factory Floor interview with Avie Tevanian, Apple's new OS boss.) Among
them, in what programming language will Rhapsody development be done? Is
Objective-C the new sheriff in town? Will we be able to continue our C/C++ and
Pascal efforts? And what about Java?
As we go to press, these issues are still not finalized. The story so far seems to be "all
of the above." Objective-C is the language for NEXTSTEP, and should provide the most
intimate access to Rhapsody. So far, it looks like C, C++, Pascal, etc. will all be
supported, though in a slightly more distant relationship. Objective-C and Java
support dynamic binding. C and Pascal support static binding, and C++ supports late
binding.
In a nutshell, binding connects a called function to the function caller. Static binding
means that the function being called is determined as the program is compiled. Though
you can use function pointers to delay binding decisions in C, typically your binding
decisions are made when you compile.
Dynamic binding is the opposite of static binding. The binding decision is delayed until
runtime. This allows you to add components to your program while it is still running.
If the runtime environment is designed to support this (and Rhapsody should be), it
opens up a lot of interesting possibilities.
The C++ language supports a limited version of dynamic binding called late binding. In
C++, a function call must type-match exactly the called function (called static typing)
or else type-match exactly an inherited function. Though C++ virtual functions allow
you to delay the binding until runtime, the type constraints still apply. Late binding is
still restricted. Dynamic binding is unconstrained.
Java uses the same binding mechanism as Objective-C. Java offers the advantage of
being a cross-platform solution, as well as tightly integrated with the Internet. It
seems likely that Java will continue to grow and is likely to play a large role in
Rhapsody.
What does all this mean for you? If you've been following this column over the past
few months, you've already gotten a handle on Java. Over the next few months, we'll dig
into Objective-C, starting with a review of some object programming terminology and
a first look at the language syntax.
Finally, you can call the NeXT order desk at 800-TRY-NEXT (800-879-6398) to
order books, manuals and software directly from NeXT, including "OpenStep
Object-Oriented Programming and the Objective-C Language", "Enterprise Objects
Framework Developer's Guide (for EOF 2.0)", "Working with Interface Builder (for
Enterprise Objects Framework)", and "Discovering OPENSTEP: A Developer Tutorial
(for Windows NT).
Some Object Programming Terminology
Before we move on to the basics of Objective-C syntax, let's review a bit of object
programming terminology, just to make sure we are all on the same page. We've
already talked about dynamic, static, and late binding. Here are a few more.
Instances, methods, and instance variables. Just as in C++, an Objective-C class
definition is a template for the creation of individual objects, also known as instances.
The functions within a class (member functions) are known as methods, and the
variables (data members) are known as instance variables.
Messages
In C++, an object's member function gets called. In Objective-C, a message is sent to
an instance, known as the receiver. At runtime, the appropriate receiver method
capable of handling the message is determined and the method is called.
Interface, implementation, and encapsulation
The interface to a class is the set of external methods defined for that class. The
implementation is the internal workings of the class. The idea here is to keep the inner
workings hidden from the user of a class, forcing them to access an instance via its
interface. This mechanism is known as encapsulation. In Objective-C, all instance
variables are encapsulated and access to them is limited to methods defined for the
class.
Inheritance
Inheritance in Objective-C works pretty much as it does in C++. The parent class is
known as a superclass and derived classes are known as subclasses.
A First Look at the Objective-C Language
Objective-C starts off with all the standard syntax of C. Objective-C source code files
use the extension ".m", while header files stick with the extension ".h".
Objective-C features a generic object pointer type called id.
id myObject;
An id is designed as a generic pointer to an object's instance variables. The previous
line of code didn't actually allocate an object. It created a pointer which will eventually
be used to allocate the object. nil is defined as an id with a value of 0.
By using a generic object pointer type, Objective-C delays the type binding decisions
until run time. This is a good thing, but it also puts a bit of extra overhead on the
run-time system. Basically, in the NeXT world, all objects are derived from the root
class Object. Object features an isa variable which is inherited by all Object
subclasses (which should be all classes in your program). The isa instance variable
specifies the class to which the object belongs.
Earlier, we talked about the separation of interface and implementation. In
Objective-C, you declare the classes interface like this
MySuperClass
{
instance variable declarations
}
method declarations
Objective-C supports the standard C compiler directives that start with "#". In
addition, Objective-C adds Objective-C specific compiler directives which start with
"@". As you might expect, class names start with an upper case letter and variable
names with a lower case letter. By convention, all identifiers are named using
intercaps, yielding names like myVariable and MyClass.
Instance variable declarations are done just as they are in C and C++, though the type
"id" is used pretty frequently in Objective-C and, obviously, is not built in to C or
C++.
Method declarations are pretty funky. Here's a sample:
- (int)getX:(int)x andY:(int)y;
The leading minus sign marks this function as an instance method. A leading plus sign
("+") marks the method as a class method. (A class method is sort of like a static
method in C++. We'll talk about class objects and class methods in a future column.)
The return type is specified in parentheses, just as if it were a typecast. If you leave
off the return type, it defaults to the type id (just as a C function defaults to int if you
leave off the return type). Note that a function that is not a method still defaults to a
return type of int.
The name of the method specified above is getX:andY: and includes the colons in the
name. Weird, eh? The idea is to have each chunk of the method end with a colon and
correspond to a parameter. In this case, there are two parameters, x and y. The type of
each parameter is also specified by a typecasting-like mechanism. Both x and y are
ints.
Here's another example:
- getObj1:object1 andObj2:object2;
Note that this time all the type information was left out of the declaration. The return
type and type of both arguments are the same, the default type "id".
Here's a sample class interface:
#import "Object.h
Object
{
idmyVar;
}
- init;
- getLastObject:lastObject;
This interface declares a class named MyClass derived from the class Object. MyClass
features a single variable, an id named myVar, and two methods, one named init and one
named getLastObject, both of which return an id.
Note that the interface, which lives in a ".h" file, starts off with a #import compiler
directive. #import replaces the #ifdef business you use in C++ to make sure you don't
include an include file twice. Use #import to include any header files you need to
include. Alternatively, you can just declare the classes you reference using the @class
directive.
This directive tells the compiler that Object is a class. That's it. This delays any type
analysis until run-time and can solve some knotty cross-dependancy problems where
classes refer to each other. Bottom line, use the @class directive if you can get away
with it, otherwise #import the classes' header file.
The implementation of a class looks like this:
MySuperClass
{
instance variable declarations
}
method definitions
Gee, doesn't this look familiar? Yup, the implementation looks almost identical to the
interface. The differences? The implementation lives in a ".m" file instead of in a ".h
file and the method definitions replace the method declarations in the interface. Also,
you are required to #import your classes' interface file in the implementation file.
One nice benefit of this last fact is that you can leave the superclass and the instance
variable declarations out of the implementation.
Here's another look:
#import "MyClass.h
Till Next Month...
Hopefully, you've got a feel for the basic structure of an Objective-C program. Next
month, we'll talk about message receivers and message syntax, and present our first
Objective-C program. To get a head start, check out the Objective-C specification on
the NeXT web site. (See the URL earlier in the column.) You can buy the NEXTSTEP
environment running under NeXT, WinNT, and on top of Mach. Also, you might want to
check out CodeBuilder from Tenon InterSystems. CodeBuilder runs on a Mac and comes
with (among a LOT of other stuff) an Objective-C compiler. You might also want to
check out Apple's web site to find out the current release schedule for Rhapsody tool
betas and the Metrowerks web site to find the status of their Rhapsody tools.