Exercise 9-4 Kochan 2.0. A question

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

  1. 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. 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. thread starter macrumors 6502

    Joined:
    Jan 3, 2009
    #3
    Answer for 9-4???
    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. macrumors newbie

    TotalLuck

    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. 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. 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. macrumors newbie

    TotalLuck

    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;
    -(id) add:(id) f;
    -(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
    /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSObjectController.h:59: warning: using '-(void)add:(id)sender'
    /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
    /[B]Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSObjectController.h:59: warning: using '-(void)add:(id)sender'[/B]
    /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. 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 :D

    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:

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

    - (void)add: (id)sender

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

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

    Cheers,

    Steve Kochan
     
  9. macrumors newbie

    TotalLuck

    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. 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. 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
     

Share This Page