From: shirley@fdr.uucp (Bill Shirley [CSC])
Subject: Objective-C Simple Sample Program - FAQ
Followup-To: comp.lang.objective-c
Summary: A simple Objective-C program to give a sample of the syntax
	to someone unfamiliar with the language.  
Supersedes: <objc-prog_720977406@fdr.jsc.nasa.edu>
Organization: nasa-jsc
Date: Fri, 6 Nov 1992 19:23:49 GMT
Expires: 20 Dec 1992 19:20:44 GMT

Archive-name: Objective-C/sample-program
Last-modified: 1992/11/01
Version: 1.0

		A S[ia]mple Objective-C Program
	(a companion to the comp.lang.Objective-C FAQ file)

// This is a comment.  Everything to the right of a double slash
// is ignored (until an end of line is reached).

/*
 * This is too, that's what superset of ANSI C means; You can do
 *  anything you can do in C in Objective-C.  (not to suggest that
 *  you should, only that you could.)
 */

// The first thing we do is bring in some include files, as in
// C.  However, we'll use the "import" statement which guarantees
// that the file isn't included more than once.

// <objc/Object.h> is not really needed, because it is #imported
// by the Queue and Stack headers, but we (as object users) don't
// necessarily know that, so it is good practice to #import it 
// here.  (When the processer reaches #import <objc/Object.h>
// in the Queue and Stack headers, it will not include it.)

#import <stdio.h>
#import <objc/Object.h>
#import "Queue.h"
#import "Stack.h"

// GNU gcc for some reason passes moral judgement on the useage
// of #import, but still allows it.  They suggest you use #ifndefs
// in all of your header files to eliminate multiple includes.

// That brought in class definitions for Objects, Queues, and
// Stacks.  Queue and Stack are classes of my own construction,
// and I'm not going to go into details here.  You don't need
// to know how they work.  The Object class is the basis for
// all other classes, which is why it gets brought in first.

// Classes are the one real extension which Objective C adds to
// C.  A class is a description of a collection of data, like a
// C structure, and the methods by which that data may be accessed
// or manipulated.  Instances of a class are called objects, and
// methods are invoked by sending messages to either the class itself,
// to produce objects, or to those objects.  The recipient of a message
// is called a "receiver".  The form of a message is:
//
//	[receiver method andMaybeSomeArguments]
//
// the receiver and method components are mandatory, as are 
// the square brackets surrounding the message.  Additional
// arguments may or may not be present, depending upon the
// method definition.  Messages may appear anywhere a statement
// is allowed in C.

// Two simple Class definitions follow.  Both inherit
// directly from the base class "Object".  This gives
// them lots of nice properties, not the least of which
// is the ability to be referenced by any pointer of the
// generic object type "id".  All objects can be pointed
// to by any id variable, and the default return type from
// methods is id.  This allows messages to be embedded in
// other messages, either as receivers or arguments.

// An Int object allocates space for a single integer.
// The "report" message causes it to report its value.
// Everything between the @implementation and the @end
// is part of the class definition...

@implementation Int: Object	// Int is derived from Object
{
    int value;		// This is the data portion.  Like a struct.
}

// The following are the method definitions.  The "+" means this
// is a class method, i.e., a method that deals with classes instead
// on instances.  In this case it is a factory method, or one which
// creates and returns a new instance of a class  The body of the
// method is between braces, like a C function.

// Self is a special variable which may only be used within a method
// and means the receiver of the message which invoked this message.
// Super means that when searching for the method for this message
// start in the parent class of the present implementation.  This
// does not, necessarily, have any relation to the value of self.

+ makeRoomFor: (int) i
{
  id  anInstance;

  anInstance  = [super new];
  value = i;
  return anInstance;
}

// It is standard for methods that do not need to return any
// special value to instead return self.  This allows for a 
// nested syntax of method calls.

// The "-" in front of report means that it's an instance method,
// i.e., how a particular object should respond.

- report
{
  printf("%4d", value);
  return self;
}

@end


// Same for a Float object, but for the obvious difference that
// it works with floats.
// Note polymorphism -- methods have same names as in the Int class.

@implementation Float: Object
{
  float value;
}

// Sometimes a factory method is written in the following manner.  This
// is not strictly correct, but since _self_ is a local variable, no 
// harm is done.  It is also quite common to see this in code from the
// net, so it is included here.  In this case _self_, which is a class,
// is assigned to return a value from [super new], which is an instance.
// It may even help the compiler optimize if there is no assignment to
// self while in a class method.

+ makeRoomFor: (float) x
{
  self = [super new];
  value = x;
  return self;
}

- report
{
  printf("%4.1f", value);
  return self;
}

@end

void main()
{
    // First we create instances of "Stack" and "Queue" data structures

    id queue = [Queue new];
    id stack = [Stack new];
    int i;

    for (i = 5; i > -6; --i)
    {
	// We alternate putting Int's and Floats onto the queue and
	// stack, based on whether "i" is odd or even.  Whatever
	// type goes on the queue, the opposite goes on the stack.

	[queue put: (i & 1) ? [Int makeRoomFor: i] : [Float makeRoomFor: i]];
	[stack put: (i & 1) ? [Float makeRoomFor: i] : [Int makeRoomFor: i]];
    }
    while ([queue size] && [stack size])
    {
	// The following illustrates run-time binding.  Will report be
	// invoked for a Float object or an Int object?  We don't know
	// ahead of time, but with run-time binding and polymorphism
	// it works the way we like.  The burden is on the class
	// implementor rather than the class user.  In fact, we
	// could add another class (String?  Complex?) and toss
	// instances onto the Stack and Queue without having to
	// change the following lines at all.

	// Both classes, Int and Float, just happen to implement the
	// method 'report'.  They do not need to inherit from some
	// object 'Reportable', only to implement the report method.
	// If one did not implement the method, the message would
	// not be sent.

	printf("queue=");	[[[queue get] report] free];
	printf(", stack=");	[[[stack get] report] free];
	putchar('\n');
    }
}

______
If you have any questions, corrections, comment, suggestions pass them
along.  I can be reached directly at <shirley@krakatoa.jsc.nasa.gov> or you
can post to the news group (comp.lang.objective-c)

Thanks to Paul J. Sanchez, paul@music.sie.arizona.edu, for writing this
program.
-- 
 Bill Shirley
 shirley@fdr.jsc.nasa.gov
-- 
 /					\
/ ``Drug War'' - a comfortable euphemism \
\    for waging war on our own citizens. /	Bill Shirley
 \					/	shirley@fdr.jsc.nasa.gov