Archives
 
 
 
  Special
 
 
 
  About Us
 
 
 

Newsletter
Free E-mail Newsletter from BYTE.com

 
    
           
Visit the home page Browse the four-year online archive Download platform-neutral CPU/FPU benchmarks Find information for advertisers, authors, vendors, subscribers Request free information on products written about or advertised in BYTE Submit a press release, or scan recent announcements Talk with BYTE's staff and readers about products and technologies

ArticlesAn Introduction to Objective-C


June 1997 / Core Technologies / An Introduction to Objective-C

While similar to C++, this programming language has differences that make OOP easier.

Justin Morgan

Since its acquisition by Apple, Next's OpenStep cross-platform environment has become a critical part of the company's OS strategy. The Rhapsody OS uses OpenStep's cross-platform development tool suite and several object frameworks (i.e., libraries).

For anyone who's used a GUI builder and an integrated development environment (IDE), the developer tools will be a snap to use. However, to leverage their full power, it's necessary to learn an uncommon object-oriented (OO) variety of C call ed Objective-C. This ha s become a source of angst for Macintosh C++ developers who must learn a new programming language.

This article offers a gentle introduction to Objective-C that C++ programmers can easily understand. It assumes familiarity with common OO concepts, such as class, inheritance, and method (known as member function in C++).

Objective-C is not as large and complex as C++, yet it's fully OO and supports inheritance, encapsulation, and polymorphism. Like C++, Objective-C is a "hybrid" language; in other words, it's an ANSI C superset that supports standard C scalar types, such as int , in addition to object types, such as NSArray .

Objective-C's run-time system allows for the creation of dynamic, extensible programs. The run-time facilitates the building of bundles, which consist of one or more compiled classes that can be dynamically loaded or linked into a running program. The language's dynamic typing and binding go hand-in-hand with dynamic loading. Ob jective-C allows instance-variable objects to be a generic type, id, which means the variable's class is not known until the program is running (i.e., the variable's class is not fixed at compile time). Once an object has been typed, the run-time automatically binds the appropriate class methods to the instance while the program is running.

The Class Interface

By convention, the source code for an Objective-C class is divided into a public interface and a private implementation. The public-interface declarations can be found in an appropriately named file suffixed with .h . Here I'll investigate the structure of an interface file by declaring a simple class called Pet. The listing "Pet-Class Interface (Pet.h)" contains the public interface for this class.

A colon separates the class name from the superclass name. In this case, Pet 's superclass is NSObject -- the root class -- which is declared in the Foundation Kit. NSObject is the only class without a superclass. (Apple prefixes Rhapsody class names with NS to prevent namespace collisions with classes.)

In C++, an object is simply a glorified structure. In Objective-C, each object is a pointer to a structure. This distinction is important when declaring instance variables, as you'll see below.

The first declared variable is the pet's name . This variable's type is statically declared as NSString , which is a Foundation Kit object that encapsulates a Unicode-compliant string. Remember that objects are pointers to structures, so the asterisk is required in front of name . If you didn't know name 's class type at compile time, you could dynamically type it to id , but you would lose some compile-time error checking. The second instance variable, age , is declared in standard ANSI C fashion.

Declaring Methods

In almost every OO language, methods come in two flavors: instance methods and class methods. In this regard, Objective-C follows the same conventions as C++. But Objective-C methods can override any inherited method. In C++ jargon, it can be said that all Objective-C member functions are "virtual."

A method's return type and its argument types can be ANSI C scalars or Objective-C objects. Arguments and return values that are objects can be statically declared (e.g., NSArray ) or dynamically declared (e.g., id ). Unlike ANSI C, Objective-C's default type is id , not int .

When you write interface declarations, instance methods are preceded with a minus sign, and class methods are preceded by a plus sign. (It so happens that the Pet class consists only of instance methods.) Each method name is separated into one or more key words, each suffixed with a colon to separate it from the argument name. The colons are considered part of the method's unique name.

The class-implementation file is shown in the listing "Pet -Class Implementation (Pet.m)" . This is where the Objective-C methods are defined for your class. Note how the instance methods provide external access to the name and age instance variables. Rhapsody uses this convention extensively; almost every publicly accessible instance variable should have a set method (e.g., setAge: ) and a get method (e.g., age ).

Structurally, Objective-C methods are defined similarly to ANSI C functions. When defining a method, you first state the method name (from the interface) and then follow it with a code block that contains the algorithms you want to perform. The code block looks just like a C function block with one important difference: You can mix Objective-C messages with regular ANSI C code.

Using Messages

Defining classes, creating instances, and sending messages are the essence of object-oriented programming (OOP). Once you define a class, you need to send messages to objects. Below are a couple of sa mple message expressions.

  [myDog setName:@"Rover"];
  [myDog setAge:3];

Here you're using the class methods setName and setAge in actual message expressions. Square brackets must be placed around the receiver and the message. The message's receiver is an instance of the Pet class (note how the receiver is always placed before the message). The message arguments are an NSString instance (the unusual @" construct begins a literal NSString containing "Rover") and a literal integer (3).

You can put an Objective-C message expression anywhere you'd put an ANSI C function call. Objective-C also allows you to nest messages. When nesting, the return value for the innermost message expression is used as the receiver for the next expression, and so on.

The listing "A Simple Objective-C Program (PetTest.m)" is basically an ANSI C main() function that contains some Objective-C messages. Since the program uses O bjective-C, you suffix the filename with .m rather than with .c .

The first line of code,

myDog = [[Pet alloc] init];

warrants further explanation. This is an example of a nested message expression. Whenever you create a new Objective-C object, you must first allocate memory for its instance variables and then initialize the object. By convention, rather than doing this on two separate lines, you ask the Pet class to allocate space for a new instance and then initialize the allocated instance -- all in one line of code.

Since the Pet class inherits the methods alloc and init from NSObject , it already has the necessary machinery to create instances of itself. The return value from the outermost expression is a new Pet instance, which is assigned to the myDog local variable. The last line in the program uses a standard printf() function to display the contents of myDog .

The World of Objective-C

Objective-C is a simple language that's easy to learn and use. C++ programmers who have already switched to Objective-C often rave about the clear syntax and vast flexibility that it provides. Although Java is more flexible than C++, it still retains C++'s obscure messaging syntax, and most developers agree that Java is just not ready for the creation of industrial-strength applications.

You can obtain further information about Objective-C development from Apple's developer site ( http://devworld.apple.com ), from Next Computer's Web site ( http://www.next.com ), and from Metrower ks' Web site ( http://www.metrowerks.com ).


Pet-Class Interface (Pet.h)

#import <Foundation/NSObject.>              // Must import my superclass
#import <Foundation/NSString.h>             // Required for 'name' variable
@interface Pet : NSObject                   // Start of class declaration
{                                           // Start of instance-variable block
  NSString  *name;                          // Object instance variable
  int          age;                         // Scalar instance variable
}                                           // End of instance-variable block
// Accessors for 'name'                     // Start of method declarations
- (void)setName:(NSString *)newName;  
- (NSString *)name;
// Accessors for 'age'
- (
void)setAge:(int)newAge;
- (int)age;
@end                                        // End of class declaration




Pet-Class Implementation (Pet.m)

#import "Pet.h"                             // Must import my interface
@implementation Pet                         // Start of class definition
- (void)setName:(NSString *)newName
{
  [name autorelease];                       // Decrement reference count of old name
  name = [newName retain];                  // Increase new name's count and
                                            // assign newName to 'name' variable
}
  
- (NSString *)name
{
  return name;
}
- (void)setAge:(int)newAge
{
  age = newAge;
}
- (int)age
{
  return age;
}
@end                                        // End of class definition




A Simple Objective-C Program (PetTest.m)

#import "Pet.h"                             // Required for 'myDog' variable
main ()
{

  Pet *myDog;                               // Local object variable
  
  myDog = [[Pet alloc] init];               // Allocate memory and initialize
  [myDog setName:@"Rover"];                 // @"Rover" is a literal NSString
  [myDog setAge:3];
  
  printf("My dog's name is '%s' and he is %d years old.\n",
     [[myDog name] cString],                // cString gets a char* from an NSString
     [myDog age]);
}




Justin Morgan has been programming OpenStep/NextStep since it was available only in a black cube. He is a contractor at AT&T Wireless Services (Kirkland, WA). You can reach him at jmorgan@objectronics.com .

Up to the Core Technologies section contentsGo to previous article: SearchSend a comment on this articleSubscribe to BYTE or BYTE on CD-ROM  
Flexible C++
Matthew Wilson
My approach to software engineering is far more pragmatic than it is theoretical--and no language better exemplifies this than C++.

more...

BYTE Digest

BYTE Digest editors every month analyze and evaluate the best articles from Information Week, EE Times, Dr. Dobb's Journal, Network Computing, Sys Admin, and dozens of other CMP publications—bringing you critical news and information about wireless communication, computer security, software development, embedded systems, and more!

Find out more

BYTE.com Store

BYTE CD-ROM
NOW, on one CD-ROM, you can instantly access more than 8 years of BYTE.
 
The Best of BYTE Volume 1: Programming Languages
The Best of BYTE
Volume 1: Programming Languages
In this issue of Best of BYTE, we bring together some of the leading programming language designers and implementors...

Copyright © 2005 CMP Media LLC, Privacy Policy, Your California Privacy rights, Terms of Service
Site comments: webmaster@byte.com
SDMG Web Sites: BYTE.com, C/C++ Users Journal, Dr. Dobb's Journal, MSDN Magazine, New Architect, SD Expo, SD Magazine, Sys Admin, The Perl Journal, UnixReview.com, Windows Developer Network