Page 1 of 1

Objective C Tutorial #2 Fun with OOP Rate Topic: -----

#1 GWatt   User is offline

  • member icon

Reputation: 309
  • View blog
  • Posts: 3,105
  • Joined: 01-December 05

Posted 08 November 2008 - 03:48 PM

In the previous Objective C tutorial we examined some of the more basic features of Objective C. In this one we're going to hit some of the more in depth aspects of Obj-C. Especially one pertaining to OOP. Also, all of the Obj-C code I use is designed to work with the libraries developed by NextStep. These libraries are included with XCode, as well as GNUStep. If you have a Mac with XCode you have everything you need. If you are running Linux or Windows then you will need to download GNUstep.

The first is some terminology. In the previous tutorial I mentioned objects, methods, and arguments. That is not exactly correct. Obj-C has receivers, selectors, and messages. Receivers are analogous to objects, selectors to methods, and messages to arguments, but if you're talking with Obj-C programmers it's best to have the terminology right. Also Obj-C does not have constructors. It has allocators and initializers. There is a difference between constructors and initializers. The most visible one being that Obj-C initializers have a return value.

Secondly, Obj-C is a weakly/loosely/dynamically typed language. (I prefer dynamic; it sounds cooler.) This means that all binding is done at runtime. Unlike Java or C++ you can call a selector that doesn't exist for that receiver. The compiler will only generate a warning. However, the code will fail at runtime if the selector does not exist for that receiver. Below is an example of this.
/*
 * Pets.m
 *
 * Graham Watt
*/

#import "Animal.h"
#import "Dog.h"
#import "Cat.h"
#import <stdio.h>
#import <Foundation/NSAutoreleasePool.h>

int main()
{
	//why worry about memory management, hence NSAutoreleasePool
	NSAutoreleasePool *pool = [ [NSAutoreleasePool alloc] init];
	
	Animal *dog = [ [Dog alloc] initDogWithName: @"Rufus" andAge: 2];
	Animal *cat = [ [Cat alloc] initCatWithName: @"Boris" andAge: 3];
	
	printf ("%s is a %s and is %d years old\n",
		[ [dog getName] UTF8String],
		[ [dog getType] UTF8String],
		[dog getAge] );
	/*
	 * The following line will generate a compiler warning because
	 * not every animal can bark
	*/
	printf ("%s says \"%s\"\n", [ [dog getName] UTF8String], [ [dog bark] UTF8String] );
		
	printf ("%s is a %s and is %d years old\n",
		[ [cat getName] UTF8String],
		[ [cat getType] UTF8String],
		[cat getAge] );
	printf ("%s says \"%s\"\n", [ [cat getName] UTF8String],
		[ [cat meow] UTF8String] );

	/*
	 * Both of the following two lines would cause the program to die
	 * because cats don't bark and dogs don't meow.
	*/
	//printf("%s says \"%s\"\n", [ [dog getName] UTF8String], [ [dog meow] UTF8String]);
	//printf("%s says \"%s\"\n", [ [cat getName] UTF8String], [ [cat bark] UTF8String]);
	
	return 0;
}



Thirdly, Obj-C sort of doesn't support generics. In Java/C++ you would do something like this:
Vector<String> vec = new Vector<String> ();


You cannot do that in Obj-C. Instead, Obj-C has a type called id that assumes the programmer knows what he/she is doing and will implicitly convert the receiver to the appropriate type based on the context. See:
/*
 * Generics.m
 *
 * Graham Watt
*/

#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
#import "Dog.h"
#import "Cat.h"
#import <stdio.h>

int main()
{
	NSAutoreleasePool *pool = [ [NSAutoreleasePool alloc] init];
	NSMutableArray *array = [ [NSMutableArray alloc] init];
	[array addObject: [ [Dog alloc] initDogWithName: @"Rufus" andAge: 2] ];
	[array addObject: [ [Cat alloc] initCatWithName: @"Brois" andAge: 3] ];
	
	printf("%s says %s\n", 
		[ [ [array objectAtIndex: 0] getName] UTF8String], 
		[ [ [array objectAtIndex: 0] bark] UTF8String] );
	printf("%s says %s\n", 
		[ [ [array objectAtIndex: 1] getName] UTF8String],
		[ [ [array objectAtIndex: 1] meow] UTF8String] );

	return 0;
}

In the two printf statements I use absolutely no typecast of any kind. The only context the runtime has to determine the receiver type is which selector I use. If I called meow for the first receiver or bark for the second there would still be no compiler warning, but the program would fail.
NOTE: when you use id you don't put an asterisk in the declaration like you would for other classes. id is already a pointer to a class.
I personally think using id is better than using generics. It's more intuitive and I believe that C++ templates are processed at compile time and not at runtime.

In closing, I think that Objective C has much to offer the OOP world but is overlooked because the syntax is quite funny to those from a C++/Java background. Obj-C is more flexible by nature than either Java or C++. It does not require a homogenous class hierarchy like Java does (everything goes back to object class) but unlike C++ it is much easier to inherit from a parent class than define your own "orphaned" class. I find it a nice balance between the two.

I have included as a download all of the code I developed for this tutorial, all the instructions needed for compiling, as well as a pdf file of the tutorial itself.

Tutorial files

Is This A Good Question/Topic? 0
  • +

Page 1 of 1