Tuesday 23 June 2009

Chapter 9 - Polymorphism, Dynamic Typing and Dynamic Binding

Comment

I think I understand the fundamentals behind 'polymorphism'. To summarise, the main advantage lies from being able to invoke a method without worrying what class that method derives from. Example being you can use 'dynamic typing' in order to invoke a method on a generic object type, at runtime 'dynamic binding' will dictate whether the method it uses is from ClassA or ClassB depending whether the data held in the generic object type is of ClassA or ClassB respectively.


Exercises

1. What will happen if you insert the message expression

[compResult reduce];

into Program 9.1 after the addition is performed (but before compResult is released)? Try it and see.


ANS - Nothing will happen since 'reduce' is not a method of the Complex class and the object 'compResult' has been defined as being an object of the Complex class which contains no such method.


Tested program and its console output.


#import

#import "Complex.h"


int main (int argc, const char * argv[]) {

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


Complex *c1 = [[Complex alloc] init];

Complex *c2 = [[Complex alloc] init];

Complex *compResult;

[c1 setReal: 18.0 andImaginary: 2.5];

[c2 setReal: -5.0 andImaginary: 3.2];

//add and print two complex numbers

[c1 print]; NSLog (@" +"); [c2 print];

NSLog (@"---------");

compResult = [c1 add: c2];

[compResult print];

NSLog (@"\n");

[compResult reduce];

[c1 release];

[c2 release];

[compResult release];

[pool drain];

return 0;

}


[Session started at 2009-06-23 22:15:38 +0100.]

2009-06-23 22:15:38.112 Ex1[394:10b] 18 + 2.5i

2009-06-23 22:15:38.114 Ex1[394:10b] +

2009-06-23 22:15:38.114 Ex1[394:10b] -5 + 3.2i

2009-06-23 22:15:38.115 Ex1[394:10b] ---------

2009-06-23 22:15:38.115 Ex1[394:10b] 13 + 5.7i

2009-06-23 22:15:38.115 Ex1[394:10b]

2009-06-23 22:15:38.116 Ex1[394:10b] *** -[Complex reduce]: unrecognized selector sent to instance 0x104c90

2009-06-23 22:15:38.117 Ex1[394:10b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[Complex reduce]: unrecognized selector sent to instance 0x104c90'


Literally translates to: 'major crash related to an unrecognised method call (or selector) being sent to a specific area of memory.


2. Can the id variable dataValue, as defined in Program 9.2, be assigned a Rectangle object as you defined it in Chapter 8? That is, is the statement

dataValue = [[Rectangle alloc] init];

valid? Why or why not?


ANS - It is valid as although it is a generic object type, it is still able to inherit the attributes of other classified object. The advantage being it can primarily act as a Rectangle object but then be reclassified as a Complex object.


3. Add a print method to your XYPoint class defined in Chapter 8. Have it display the point in the format (x, y). Then modify Program 9.2 to incorporate an XYPoint object. Have the modified program create an XYPoint object, set its value, assign it to the id variable dataValue, and then display its value.


ANS - Copy and Paste of added XYPoint method and modified Program 9.2 along with its console output.


// XYPoint.m

-(void) print

{

NSLog (@"point (%i, %i)", x, y);

}


// main program

#import

#import "XYPoint.h"


int main (int argc, const char * argv[]) {

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


id dataValue;

XYPoint *point = [[XYPoint alloc] init];

[point setX: 5 andY: 8];

dataValue = point;

[dataValue print];

[point release];

[pool drain];

return 0;

}


[Session started at 2009-06-23 13:50:14 +0100.]

2009-06-23 13:50:14.673 Ex2[475:10b] point (5, 8)


The Debugger has exited with status 0.


4. Based on the discussions about argument and return types in this chapter, modify both add: methods in the Fraction and Complex classes to take and return id objects. Then write a program that incorporates the following code sequence:

result = [dataValue1 add: dataValue2];

[result print];

Here, result, dataValue1 and dataValue2 are id objects. Make sure you set dataValue1 and dataValue2 appropriately in your program and release all objects before your program terminates.


ANS - Modified methods made to both class interface and implementation files. Copy and Paste of main program and its console output. Couldn't get this one to compile due to syntax errors.


#import

#import "Fraction.h"

#import "Complex.h"


int main (int argc, const char * argv[]) {

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


Fraction *aFrac = [[Fraction alloc] init];

Complex *aComp = [[Fraction alloc] init];

id result;

id dataValue1;

id dataValue2;

[aFrac setNumerator: 1 andDenominator: 4];

dataValue1 = aFrac;

[aFrac setNumerator: 1 andDenominator: 2];

dataValue2 = aFrac;

[aFrac release];

result = [dataValue1 add: dataValue2];

[result print];

[aComp setReal: 3.0 andImaginary: 1.5];

dataValue1 = aComp;

[aComp setReal: 10.0 andImaginary: 4.5];

dataValue2 = aComp

[aComp release];

result = [dataValue1 add: dataValue2];

[result print];

[result release];

[dataValue1 release];

[dataValue2 release];

[pool drain];

return 0;

}


5. Given the Fraction and Complex class definitions you have been using in this text and the following definitions


Fraction *fraction = [[Fraction alloc] init];

Complex *complex = [[Complex alloc] init];

id number = [[Complex alloc] init];


determine the return value from the following message xpressions. Then type them into a program to verify the results.


[fraction isMemberOfClass: [Complex class]];

[complex isMemberOfClass: [NSObject class]];

[complex isKindOfClass: [NSObject class]];

[fraction isKindOfClass: [Fraction class]];

[fraction respondsToSelector: @selector (print)];

[complex respondsToSelector: @selector (print)];

[Fraction instancesRespondToSelector: @selector (print)];

[number respondsToSelector: @selector (print)];

[number isKindOfClass: [Complex class]];

[number respondsToSelector: @selector (release)];

[[number class] respondsToSelector: @selector (alloc)];


ANS - Expected output and console output


Expected Output

NO - fraction is an instance of the Fraction class

NO - complex is an instance of the Complex class and not the NSObject class

YES

YES

YES

YES

YES

YES

YES

YES

NO - because number is not a class, it is an object belonging to a class



[Session started at 2009-06-23 23:17:18 +0100.]

2009-06-23 23:17:18.119 Ex5[746:10b] NO

2009-06-23 23:17:18.121 Ex5[746:10b] NO

2009-06-23 23:17:18.121 Ex5[746:10b] YES

2009-06-23 23:17:18.121 Ex5[746:10b] YES

2009-06-23 23:17:18.122 Ex5[746:10b] YES

2009-06-23 23:17:18.122 Ex5[746:10b] YES

2009-06-23 23:17:18.122 Ex5[746:10b] YES

2009-06-23 23:17:18.123 Ex5[746:10b] YES

2009-06-23 23:17:18.123 Ex5[746:10b] YES

2009-06-23 23:17:18.123 Ex5[746:10b] YES

2009-06-23 23:17:18.124 Ex5[746:10b] YES


The Debugger has exited with status 0.


6. Modify the Calculator class you developed in the exercise from Chapter 4 so that division is done in an @try block. If the division throws an exception, log an error message and continue program execution.


ANS - Copy and Paste of all parts of program including console output. Program compiles but receive awkward console output.


//

// Calculator.h

// Ex6

//

// Created by Waqas Arshid on 23/06/2009.

// Copyright 2009 __MyCompanyName__. All rights reserved.

//


#import



@interface Calculator : NSObject

{

double accumulator;

double memory;

}


@property double accumulator;


-(void) clear;


-(void) divide: (double) value;


@end


//

// Calculator.m

// Ex6

//

// Created by Waqas Arshid on 23/06/2009.

// Copyright 2009 __MyCompanyName__. All rights reserved.

//


#import "Calculator.h"



@implementation Calculator


@synthesize accumulator;


-(void) clear

{

accumulator = 0;

}


-(void) divide: (double) value

{

@try {

accumulator /= value;

NSLog (@"The resulting value of accumulator is: %f", accumulator);

}

@catch (NSException *exception) {

NSLog (@"Caught division by zero - error.");

}

}


@end


// main


#import

#import "Calculator.h"


int main (int argc, const char * argv[]) {

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


Calculator *deskCalc = [[Calculator alloc] init];

[deskCalc clear];

[deskCalc setAccumulator: 100.0];

[deskCalc divide: 0.0];

NSLog (@"The final result is: %f", [deskCalc accumulator]);

[deskCalc release];

[pool drain];

return 0;

}


[Session started at 2009-06-23 23:41:13 +0100.]

2009-06-23 23:41:13.132 Ex6[842:10b] The resulting value of accumulator is: inf

2009-06-23 23:41:13.133 Ex6[842:10b] The final result is: inf


The Debugger has exited with status 0.


No comments:

Post a Comment