# Exercise 9-4 Kochan 2.0. A question

Discussion in 'Mac Programming' started by mdeh, Jan 20, 2009.

1. ### mdeh macrumors 6502

Joined:
Jan 3, 2009
#1
Does this mean to modify EACH method so that EACH method can take a fraction or complex class object?

2. ### skochan macrumors regular

Joined:
Apr 1, 2006
Location:
California
#2
The Complex and Fraction classes both have add: methods. The exercise is to change the argument and return type of each add: method to take and return an id object.

Cheers,

Steve K.

3. ### mdeh thread starter macrumors 6502

Joined:
Jan 3, 2009
#3
Here is my attempt. Your input is appreciated.

Fraction.h
Code:
```
#import <Foundation/Foundation.h>
@interface Fraction : NSObject {
int numerator;
int denominator;
}
@property int numerator, denominator;
-(void) setTo: (int) n over: (int) d;
-(id) add: (id) f;
-(void) reduce;
```

Code:
```#import "Fraction.h"

@implementation Fraction;
@synthesize denominator, numerator;
-(void) print
{

NSLog(@"%i/%i ", numerator, denominator);
}

-(void) setTo: (int) n over: (int) d
{
numerator = n;
denominator = d;
}

-(id) add: (id) f
{
int resultNum, resultDenom;
Fraction* result = [[Fraction alloc] init];

resultNum = numerator *[ f denominator] + denominator * [f numerator];
resultDenom = denominator *[ f denominator];

[result setTo: resultNum over: resultDenom];
[result reduce];
return result;
}

-(double) convertToNum
{
if (denominator != 0)
return (double) numerator / denominator;
else
return 1.0;
}

-(void) reduce
{
int u, v, temp;
BOOL isNegativeNumerator = NO;
BOOL isNegativeDenominator = NO;

if ( numerator < 0)
{
isNegativeNumerator = YES;
numerator = -numerator;
}

if ( denominator < 0)
{
isNegativeDenominator = YES;
denominator = -denominator;
}

u = numerator;
v = denominator;

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

numerator /= u;
denominator /= u;

if ( isNegativeNumerator == YES || isNegativeDenominator == YES)
numerator = -numerator;
}

@end```

Complex.h

Code:
```#import <Foundation/Foundation.h>

@interface Complex : NSObject
{
float real;
float imaginary;
}

@property float real, imaginary;
-(id) add: (id) complexNumber;
-(void) setReal: (float) r andImaginary: (float) i;
-(void) print;
@end```
Complex.m

Code:
```#import "Complex.h"
@implementation Complex

@synthesize real, imaginary;

-(void) setReal: (float) r andImaginary: (float) i
{
real = r;
imaginary = i;
}

-(id) add: (id) complexNumber
{
Complex *myCx =  [[ Complex alloc ] init];
myCx.real = (real + [complexNumber real]);
myCx.imaginary = (imaginary + [complexNumber imaginary]);
return myCx;

}
-(void) print
{
NSLog(@"%g + %gi", real, imaginary);
}
@end
```
main.m

Code:
```#import "Fraction.h"
#import "Complex.h"

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
id dataVal1, dataVal2, result;
Complex *c1 = [[ Complex alloc] init];
Complex *c2 = [[ Complex alloc] init];
Fraction *f1 = [ [ Fraction alloc] init];
Fraction *f2 = [ [ Fraction alloc] init];

[c1 setReal: 67.0	andImaginary: 76.0];
[c2 setReal: 27.0	andImaginary: 72.0];
dataVal1 = c1;
dataVal2 = c2;

result = [dataVal1 add: dataVal2];
[result print];

[result release];

[f1 setTo: 4 over: 5];
[f2 setTo: 7 over: 8];

dataVal1 = f1;
dataVal2 = f2;

result = [ dataVal1 add: dataVal2];
[result print];
[result release];

[f1 release];
[f2 release];
[c1 release];
[c2 release];
[pool drain];
return 0;
}
```

4. ### TotalLuck macrumors newbie

Joined:
Jan 3, 2009
Location:
Moreno Vallley
#4
thanks Mdeh

Thanks a ton. again i was about to ask for help and there you are posting.

After pulling my hair out i see what was perplexing me.

I was trying to use f.numerator instead of [ f numerator].

So if i understand it , the dot notation is used when you/program knows what to expect from the object that was passed in. The [ f numerator] is basically saying go get this item. ( i had tried [f getNumerator] )

i don't have a problem getting the program to compile using the following
Code:
```from fraction .m
-(id) add: (id) f
{   //add fractions together

// result stores the reult of the addition

Fraction *result = [[Fraction alloc] init];
double resultNum, resultDenom , fnum ;

if ( f < 0)
{

fnum = -1 * [f numerator];
resultNum = numerator * [f denominator ] - denominator * fnum ;
resultDenom = denominator * [f denominator];
[result setTo:resultNum over: resultDenom];
}

else
{

resultNum = numerator * [f denominator ]  + (denominator * [ f numerator ]);
resultDenom = denominator * [  f denominator ];
[result setTo:resultNum over: resultDenom];
}
if (resultNum > resultDenom)
{
[result reduce];

}

return result;

}

int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];

id  result, dataValue2, dataValue1;
Fraction *f1 = [[Fraction alloc]init];
Fraction *f2 = [[Fraction alloc]init];
ComplexNumbers *c1 = [[ ComplexNumbers alloc] init];
ComplexNumbers *c2 = [[ ComplexNumbers alloc] init];

[f1 setTo:2 over:5];
[f2 setTo:5 over:8];

result = [ f1 add: f2];
[result print];
```
but when i add
Code:
```	dataValue1 = f1;
dataValue2 = f2;

result = [ dataValue1 add: dataValue2 ];
[result print];
[result release];
```
i get error
" - void value not ignored as it ought to be. "
what am i missing there?

5. ### mdeh thread starter macrumors 6502

Joined:
Jan 3, 2009
#5
There clearly is a difference. Perhaps one of the more erudite contributors could clear this up?

Code:
```i get  error
" - void value not ignored as it ought to be. "
what am i missing there?[/QUOTE]
```

I am not sure if this would make any difference, but are you releasing "result" before you use it again?

6. ### skochan macrumors regular

Joined:
Apr 1, 2006
Location:
California
#6
That's right! The dot notation cannot be used directly on id variables (you'd have to typecast it first to the appropriate object type). I should have pointed that out in the text--and I'll get it into the next printing.

Without seeing all the code, I'm guessing you have the add: method declared to return void somewhere (perhaps in the ComplexNumbers.h/.m files?). Let me know, or email the complete code to me.

Cheers,

Steve Kochan

7. ### TotalLuck macrumors newbie

Joined:
Jan 3, 2009
Location:
Moreno Vallley
#7
Thanks again steve.

Here are the files
Code:
```#import <Foundation/Foundation.h>
#import <objc/Object.h>

@interface Fraction	: NSObject
{
int numerator;
int denominator;
}

@property int numerator, denominator;

-(void) print;
-(double) convertToNum;
-(void) setTo: (int) n over: (int) d;
-(Fraction *) subtract: (Fraction *) f;
-(Fraction *) multiply: (Fraction *) f;
-(Fraction *) divide: (Fraction *)f;
-(void) reduce;

@end
```
Code:
```#import "Fraction.h"

@implementation Fraction
@synthesize numerator, denominator;

-(void) print
{
int whole, num2;
BOOL needToReduce;

if  ( numerator >= denominator)
needToReduce = YES;

if (needToReduce == YES)
{
whole = numerator / denominator;
num2 = numerator % denominator;
if (numerator % denominator == 0)
NSLog(@" %i ", whole);
else
NSLog(@" %i %i/%i ", whole, num2, denominator);
}
else
NSLog(@" %i/%i ",numerator, denominator);
}

-(double) convertToNum
{

if ( denominator != 0 )
return (double)  numerator / denominator;
else
return 1;
}

-(void) setTo: (int) n over: (int) d
{
numerator = n;
denominator = d;
}

-(id) add: (id) f
{   //add fractions together

// result stores the reult of the addition

Fraction *result = [[Fraction alloc] init];
double resultNum, resultDenom , fnum ;

if ( f < 0)
{

fnum = -1 * [f numerator];
resultNum = numerator * [f denominator ] - denominator * fnum ;
resultDenom = denominator * [f denominator];
[result setTo:resultNum over: resultDenom];
}

else
{

resultNum = numerator * [f denominator ]  + (denominator * [ f numerator ]);
resultDenom = denominator * [  f denominator ];
[result setTo:resultNum over: resultDenom];
}
if (resultNum > resultDenom)
{
[result reduce];

}

return result;

}

-(Fraction *) subtract: (Fraction *) f
{
//subtract fractions
Fraction *result = [[Fraction alloc] init];
int resultNum1, resultNum2, resultDenom, resultNum;

if ( f < 0)
{
f.numerator = -1 * f.numerator;

resultNum1 =(numerator * f.denominator) ;
resultNum2 = (denominator * f.numerator);
resultDenom = (denominator * f.denominator);

resultNum = resultNum1 + resultNum2;

[result setTo:resultNum		over: resultDenom];
}

else {

resultNum1 =(numerator * f.denominator) ;
resultNum2 = (denominator * f.numerator);
resultDenom = (denominator * f.denominator);

resultNum = resultNum1 - resultNum2;

[result setTo:resultNum		over: resultDenom];
}

if (resultNum > resultDenom)
{
[result reduce];
}

return result;
}
-(Fraction *) multiply: (Fraction *) f
{
Fraction *result = [[Fraction alloc]init];
int resultNum, resultDenom;

if ( f < 0)
{
f.numerator = -1 * f.numerator;

resultNum = numerator * f.numerator;
resultDenom = denominator * f.denominator;

[result setTo:resultNum over: resultDenom];
}
else
{

resultNum = numerator * f.numerator;
resultDenom = denominator * f.denominator;

[result setTo:resultNum over: resultDenom];
}

if (resultNum > resultDenom)
{
result.reduce;
}

return result;
}

-(Fraction *) divide: (Fraction *)f
{
Fraction *result = [[Fraction alloc]init];
int resultNum, resultDenom;

resultNum = numerator * f.denominator;
resultDenom = denominator * f.numerator;

[result setTo:resultNum over: resultDenom];

if (resultNum > resultDenom)
{
result.reduce;
}

return result;
}

-(void) reduce
{
int u = numerator;

int v = denominator;
int temp;

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

numerator /= u;
denominator /= u;

}

@end

```
Code:
```#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>

@interface ComplexNumbers : NSObject
{
double	real;
double	imaginary;
}

@property double real, imaginary;

// methods
-(void) setReal : (double) a andImaginary: (double) b;
-(void) print; // to print as  a + b(i)
-(id) add: (id)  c;

@end```
Code:
```#import "Complex.h"

@implementation ComplexNumbers

@synthesize real, imaginary;
// define methods
-(id) add: (id) c
{
id result = [[ComplexNumbers alloc] init];
double r1, imag1;

r1		= real + [c real];
imag1	= imaginary + [c imaginary];
[result setReal:r1 andImaginary:imag1];

return result;

}
-(void) setReal: (double) a  andImaginary: (double) b
{
real = a , imaginary = b;
}

-(void) print  //  print the equation
{
NSLog(@"(%g + %gi)", real, imaginary);
}

@end```
Code:
```#import <Foundation/Foundation.h>
#import "Fraction.h"
#import "Complex.h"

int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];

id  result, dataValue2, dataValue1;
Fraction *f1 = [[Fraction alloc]init];
Fraction *f2 = [[Fraction alloc]init];
ComplexNumbers *c1 = [[ ComplexNumbers alloc] init];
ComplexNumbers *c2 = [[ ComplexNumbers alloc] init];

[f1 setTo:2 over:5];
[f2 setTo:5 over:8];

result = [ f1 add: f2];
[result print];

dataValue1 = f1;
dataValue2 = f2;
result = [ dataValue1 add: dataValue2 ];

[result print];

[c1 setReal: 10 andImaginary: 2.5 ];
[c2 setReal: 14 andImaginary: 3];

result = [ c1 add: c2 ];
[result print];

dataValue1 = c1;
dataValue2 = c2;

result = [ dataValue1 add: dataValue2 ];

[result print];
[result release];

[c1 release];
[c2 release];
[f2 release];
[f1 release];
[pool drain];
return 0;

}```
i am using Xcode leopard 10.5

here is the debug
Code:
```/users/lori/Desktop/Objectve c lessons/Rectangle/main.m: In function 'main':
/Users/lori/Desktop/Objectve c lessons/Rectangle/main.m:32: warning: multiple methods named '-add:' found
/Users/lori/Desktop/Objectve c lessons/Rectangle/Fraction.h:22: warning: also found '-(id)add:(id)f'
/Users/lori/Desktop/Objectve c lessons/Rectangle/main.m:32: error: void value not ignored as it ought to be
/Users/lori/Desktop/Objectve c lessons/Rectangle/main.m:46: warning: multiple methods named '-add:' found
/Users/lori/Desktop/Objectve c lessons/Rectangle/Fraction.h:22: warning: also found '-(id)add:(id)f'
/Users/lori/Desktop/Objectve c lessons/Rectangle/main.m:46: error: void value not ignored as it ought to be

```
does it look like an error in the framework file?

8. ### skochan macrumors regular

Joined:
Apr 1, 2006
Location:
California
#8

Looks like the NSObjectController class has an add: method that returns void; thus the conflict at compile time. Use different method names (like addX). This goes back to the point made in the text about sending a message to an id type: all methods of the same name must agree in arguments and return type. This is actually a good learning exercise

By the way, you shouldn't be importing <objC/Object.h> . I don't have my book handy, but if that's from the text, it's a holdover from the first edition.

-----------
From Apple's documentation on the NSObjectController class:

Creates a new object and sets it as the receiver’s content object.

Parameters
sender
Typically the object that invoked this method.
....

-------------

Cheers,

Steve Kochan

9. ### TotalLuck macrumors newbie

Joined:
Jan 3, 2009
Location:
Moreno Vallley
#9
Thank you Steve

Yeah i forgot to delete that.. I worked through the first 5 chapters in Book 1 then got Book 2 and forgot to change some of the file #imports. so dont chase down the editor just yet.

and thanks for the help. changing to the -(id)addX fixed the problem.

10. ### mdeh thread starter macrumors 6502

Joined:
Jan 3, 2009
#10
Steve, I thought the "typecast" operator was () as in:

return (float) 7 /* where 7 is an int */

Here we use [ ..... ]. Could you elaborate a little.

Thank you.

11. ### skochan macrumors regular

Joined:
Apr 1, 2006
Location:
California
#11
Ahh, I was hoping you wouldn't ask me that. If you knew the id object f was a Fraction, you could write the following:

Code:
```((Fraction *) f).numerator
```
I'm only showing you this because you asked. But it's ugly!

Cheers,

Steve Kochan