Bookmark and Share

Objective-C Programming Tutorial


SoBackSanA


Chapter 2. Inheritance

This tutorial is written assuming you are already familiar with Object Oriented Programming either from C++ or Java.
So, I am not going to dive into the details of OO.


2.1 Forward Declaration: @class Directive

The basic structure of code using inheritance is this:

@interface ChildClass: ParentClass
...
@end

It may be obvious to those who have been writing C++/Java, just to get used to the Objective-C code, I will list a very simple code using the inheritance.
In this code, Rectangle is the ChildClass and NSObject is the ParentClass.


@Interface: <Rectangle.h>

#import <Foundation/Foundation.h>

@interface Rectangle: NSObject 
{ 
	int width; 
	int height; 
} 

@property int width, height;
-(void) setWidth: (int) w andHeight: (int) h;
-(int) area;
@end 

@Implementation: <Rectangle.m>

#import "Rectangle.h"

@implementation Rectangle 

@synthesize width, height;

//method taking 2 args
-(void) setWidth: (int) w andHeight: (int) h
{ 
	width = w;
	height = h;
} 

-(int) area { 
	return width*height;
}
@end

The main program: <main.m>

#import "Rectangle.h"
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) 
{	
      NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
      Rectangle *rect =[[Rectangle alloc] init];	
	
      //set the values
      [rect setWidth: 10 andHeight: 5];
	
      // print it
      NSLog(@"rectnagle: w = %i and h = %i",
		rect.width, rect.height);
      NSLog(@"rectnagle: area = %i",[rect area]);
	
      // free memory
      [rect release];
	
      [pool drain];
      return 0;		
}

The output is:

rectangle: w = 10 and h = 5
rectangle: area = 50 



Suppose we need a Square class and we want to use the method "area" of Rectangle class instead of making a new "area" method.
Here is the code for a Square class as a subclass of Rectangle.

Square Interface: <Square.h>

#import "Rectangle.h"

@interface Square: Rectangle

-(void) setSide: (int) s;
-(int) side;
@end

Square Implementation: <Square.m>

#import "Square.h"

@implementation Square: Rectangle

-(void) setSide: (int) s 
{
      [self setWidth: s andHeight: s];
}

-(int) side 
{
      return width;
}
@end

Our main program can be changed like this:

#import "Square.h"
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) 
{
      NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
      //Rectangle *rect =[[Rectangle alloc] init];	
	Square *square =[[Square alloc] init];

      //set the values
      [square setSide: 10];
	
      // print it
      NSLog(@"Square: side = %i",[square side]);
      NSLog(@"Square: area = %i",[square area]);
	
      // free memory
      [square release];
	
      [pool drain];
      return 0;		
}

Though we added two new methods, "setSide:" and "side", to the Square class,
we did not add an "area" method since we are inheriting it from the Rectangle class.

The output is:

Square: side = 10
Square: area = 100 

2.2 Forward Declaration: @class Directive

Our Rectangle class in the code above does not have much information.
It gives us only the size of the rectangle. Not the location.
So, let's add a new class PointXY to our Rectancle class which has data members x and y.

Here is our new Rectangle Interface.

@Interface file: <Rectangle.h>

#import <Foundation/Foundation.h>

@class PointXY;
@interface Rectangle: NSObject 
{ 
	int width; 
	int height; 
	PointXY *Origin;
} 

@property int width, height;
-(PointXY *) Origin;
-(void) setOrigin: (PointXY *) pt;
-(void) setWidth: (int) w andHeight: (int) h;
-(int) area;
@end 

Here, the new line "@class PointXY" let the compiler know what a "PointXY" is
when it sees it as one of the instance variables in the Rectangle class.
We call "@class className" as forward declaration.

Our new Rectangle Implementation.

@Implementation file: <Rectangle.m>

#import "Rectangle.h"

@implementation Rectangle 

@synthesize width, height;

-(void) setWidth: (int) w andHeight: (int) h
{ 
	width = w;
	height = h;
} 

-(int) area { 
	return width*height;
}

-(void) setOrigin: (PointXY *) pt
{
	Origin = pt;
}

-(PointXY *) Origin
{
	return Origin;
}
@end

Note that we added two method to the implementation of Rectangle:
"setOrigin:" and "Origin".

But we have not defined our PointXY class yet.

Here is the interface for PointXY class

@Interface file: <PointXY.h>

#import <Foundation/Foundation.h>

@interface PointXY: NSObject 
{ 
	int x; 
	int y; 
} 

@property int x, y;

-(void) setX: (int) xCoord andY: (int) yCoord;
@end 

Implementation for PointXY class

@Implementation file: <PointXY.m>

#import "PointXY.h"

@implementation PointXY

@synthesize x,y;
-(void) setX: (int) xCoord andY: (int) yCoord 
{ 
	x = xCoord; 
	y = yCoord; 
} 
@end 

So far, we defined 4 files:
"PointXY.m", "PointXY.h", "Rectangle.m", and "Rectangle.h".
Now, it's time to test it.

Here is our last code for the testing: <rectOrigin.m>

#import "Rectangle.h"
#import "PointXY.h"

int main (int argc, const char * argv[]) 
{
      NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
      Rectangle *rect =[[Rectangle alloc] init];	
      PointXY *point =[[PointXY alloc] init];

      //set the values
      [point setX: 100 andY: 300];
      [rect setWidth: 200 andHeight: 100];

      rect.Origin = point;
	
      // print it
      NSLog(@"Rectangle: w = %i, h = %i", rect.width, rect.height);
      NSLog(@"Recangle: Origin = (%i,%i)",
	                            rect.Origin.x, rect.Origin.y);
	
      // free memory
      [rect release];
      [point release];
	
      [pool drain];
      return 0;		
}

The output is:

Rectangle: w = 200, h = 100
Rectangle: area = 20000 
Rectangle: Origin = (100,300)



SoBackSanB