Advertisements

Objects (Part 4): Inheritance—Extending & Overriding


An object inherits various instance variables and methods from its superclass. However, the fundamental principles of inheritance also allow you to extend its superclass, as well as override inherited methods, replacing them with a different implementation. To illustrate this example, we will subclass our Fraction class with a MixedNumber class. Let’s get started!

Extending

A mixed number is a whole number plus a fractional component

Mixed Number

How would we implement a mixed number? At initial glance, it looks pretty simple—and it is! A mixed number can be simply represented with an integer as the main number component, and a Fraction object for the fractional component (in fact, a class that uses another class as part of its data storage is known as a hybrid (sub)class). But the good part about inheritance is that the instance variables from its superclass—MixedNumber inherits numerator and denominator from Fraction, so we can simply use that. Therefore, the only new ivar we need to add is the integer for the numerical portion.

 

In Xcode, open up your FractionDemo project. Click on File > New File… In the left, click on Cocoa Class, and choose Objective-C Class, make sure it’s a subclass of NSObject, and click Next. Save the File Name as MixedNumber.m, and make sure that the check box below, ‘Also create “MixedNumber.h”‘ is checked. Click Finish. This should take you to the file listings in Xcode, and open up Fraction.h in the text editor. Import “Fraction.h”, and make it a subclass of Fraction. Rather than providing the full listing, try to figure out the code by yourself. If you’re stuck, you can download the full code at the end of the post. Add an NSInteger for the wholeNumber portion, and synthesize it.

In MixedNumber.m, add the following method implementations:

- (void)setWholeNumber:(NSInteger)number andNumerator:(NSInteger)num overDenominator:(NSInteger)denom {
	self.wholeNumber = number;
	self.numerator = num;
	self.denominator = denom;
}

- (void)setWholeNumber:(NSInteger)number andFraction:(Fraction *)frac {
	self.wholeNumber = number;
	self.numerator = frac.numerator;
	self.denominator = frac.denominator;
}

- (void)display {
	NSString *numberString = [[NSString alloc] initWithFormat:@"%d", self.wholeNumber];
	NSString *numeratorString = [[NSString alloc] initWithFormat:@"%d", self.numerator];
	NSString *denominatorString = [[NSString alloc] initWithFormat:@"%d", self.denominator];
	NSLog(@"%@+(%@/%@)", numberString, numeratorString, denominatorString);
	[denominatorString release];
	[numeratorString release];
	[numberString release];
}

+ (MixedNumber *)addMixedNumber:(MixedNumber *)num1 toMixedNumber:(MixedNumber *)num2 {
	// Store result in "result"
	MixedNumber *result = [[[MixedNumber alloc] init] autorelease];
	result.wholeNumber = num1.wholeNumber + num2.wholeNumber;
	result.numerator = num1.numerator * num2.denominator + num1.denominator * num2.numerator;
	result.denominator = num1.denominator * num2.denominator;

	// Reduce
	if (result.numerator > result.denominator) {
		int extra = result.numerator / result.denominator;
		result.wholeNumber += extra;	// Taking advantage of integer division
		result.numerator -= extra * result.denominator;

		int u = result.numerator;
		int v = result.denominator;
		int temp = 0;

		// Euclid's procedure to find GCD (Greatest Common Denominator)
		// Don't worry about how this works, exactly. 

		while (v != 0) {
			temp = u % v;
			u = v;
			v = temp;
		}

		result.numerator /= u;
		result.denominator /= u;
	}

	return result;
}

Make sure to add the method declarations to the header.

A few things to note here:

  1. The first two methods are similar to the set… methods of the Fraction class—nothing new or interesting here.
  2. The -display method is interesting—it has the same name as its superclass, Fraction. This invokes the inheritance chain—the runtime will find the version of -display that is closest to MixedNumber. Therefore, it will call this latter implementation rather than Fraction‘s.
  3. The add method is a class method (for extra practice, declare and implement all four instance methods and the remaining three class methods). Here, we add the whole number portions, and properly add the fractional components. We reduce, first by checking and making sure that the fraction is actually less than one, and then using Euclid’s method to reduce our resulting fraction.

Note that a subclass can call one of its (direct) superclass’s overridden methods by using the super keyword:

[super display];

This works in much the same way as the self keyword, except that the latter refers to the current instance, while the former refers to the superclass.

A test routine for the MixedNumber class:

...
	// bFraction is declared previously
	MixedNumber *aMixedNum = [[MixedNumber alloc] init];
	MixedNumber *bMixedNum = [[MixedNumber alloc] init];
	[aMixedNum setWholeNumber:3 andNumerator:2 overDenominator:4];
	[bMixedNum setWholeNumber:4 andFraction:bFraction];

	NSLog(@"aMixedNum is"); [aMixedNum display];
	// Uses Fraction's reduce method on the fractional portion of MixedNumber
	NSLog(@"After reducing, aMixedNum is"); [aMixedNum reduce]; [aMixedNum display];

	NSLog(@"Addition: ");	
	[aMixedNum display]; NSLog(@" + "); [bMixedNum display]; NSLog(@" = ");
	[[MixedNumber addMixedNumber:aMixedNum toMixedNumber:bMixedNum] display];	
	// display is invoked on the return value of the add method

	[bFraction release];
	[aMixedNum release];
	[bMixedNum release];
	...

The code is rather self-explanatory, but make sure you understand which method is called, and which method is actually being found in the inheritance chain, especially when you start to override methods.

The output is:

aMixedNum is
3+(2/4)
After reducing, aMixedNum is
3+(1/2)
Addition: 
3+(1/2)
 + 
4+(1/3)
 = 
7+(5/6)

You can download the latest FractionDemo code by clicking here.

Advertisements
Leave a comment

5 Comments

  1. Roberto

     /  October 27, 2011

    Hi,

    Whats the difference between a class and an instance method ? How can I identify when to use one or the other ? … etc….

    Thanks in advance

    Reply
    • A class method is one that applies to a class as a whole, while an instance class acts on an instance. Imagine you have a car factory—you can call a factory method, such as change-all-colors, or you can call an instance method, such as fill-up-gas-tank on a single car. The choice to use class methods or instance methods depends on your design pattern, but in general if you need information about an instance (to access instance variables, for example), you’d use an instance method. For convenience methods (for example, UIColor has a +redColor method) or to just return the result of a calculation or a set value (maximum output of our hypothetical factory), you could use a class method.

      Reply
  2. Paul

     /  October 21, 2012

    The link to the source is dead. I gotta say it was more educational to update by hand.

    Thanks for the education.

    Reply
  3. Beth Randall

     /  July 12, 2013

    You say:

    open up “Fraction.h” in the text editor. Import “Fraction.h” …

    Don’t you mean “open up MixedNumber.h in the text editor”?

    Thanks for the tutorial!

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Advertisements
  • Welcome

    My goal is to make CupsOfCocoa into a beautiful source for beginners to the iPhone platform to get started. Subscribe below for more, and stay tuned!

  • Contact Me

    If you need to contact me for any reason, feel free to send me an email.
  • The Giving Spirit

    If you've found this site helpful, would you consider donating a little sum? Any amount is appreciated...Thanks so much!

  • Roadmap

  • Enter your email address to follow this blog and receive notifications of new posts by email.

    Join 222 other followers

  • Back to the Past

    January 2011
    S M T W T F S
    « Dec   Feb »
     1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031  
  • Time Machine

  • You count!

    • 621,851 views
  • Worldwide Stats

    free counters
  • Advertisements
%d bloggers like this: