Amazon.com Widgets Chapter 9 Exercise 4 - Which method is best?
Welcome, Guest. Please login or register.
Did you miss your activation email?
May 18, 2013, 07:31:09 PM
Home Help Search chat Login Register   
News: Read this please.The Great Kangaroo Escape Looking for reviews of the 4th ed on Amazon!   Twitter:  @skochan
                     

+  Official Forum for Programming in Objective-C (the iPhone Programming Language) - Stephen Kochan
|-+  Old Stuff
| |-+  Answers to Exercises
| | |-+  Chapter 9
| | | |-+  Chapter 9 Exercise 4 - Which method is best?
Pages: [1]   Go Down
Print
Author Topic: Chapter 9 Exercise 4 - Which method is best?  (Read 1429 times)
MarkReid
Full Member
***
Posts: 173






« on: May 09, 2009, 03:49:24 PM »

I've written my add: methods taking id object as an argument and returning an id object. However in one I assign result as an id variable and in the other I leave it as a class object.

-(id) add: (id) f
{
   // To add two fractions
   // a/b + c/d = ((a*d) + (b*c)) / (b * d)
   
   // result will store the result of the addition
   id result = [[Fraction alloc] init];
   int resultNum, resultDenom;
   
   resultNum = numerator * [f denominator] + denominator * [f numerator];
   resultDenom = denominator * [f denominator];
   
   [result setTo: resultNum over: resultDenom];
   [result reduce];
   
   return result;
   [result release];
}

AND

-(id) add: (id) f
{
   Complex *result = [[Complex alloc] init];
   
   [result setReal: real + [f real] andImaginary: imaginary + [f imaginary]];
   
   return result;
   [result release];
}

Can someone tell me which approach is best or does it not really matter?

I don't think I fully understand what
id result = [[Fraction alloc] init];
actually does so any clarification on that would be greatly appreciated too.

My understanding of it is that it performs the same function as Fraction *result but does not explicitly set the object type. As such it is dynamic typed and so it's checked at runtime to see if the methods I call on it work with it or not. Am I correct in thinking this method isn't preferred as errors may appear at runtime rather than compile time and I should use static typing when I know what type of object is being used?

Hopefully that makes sense, not sure it did to me.  Cheesy
Logged
MarkReid
Full Member
***
Posts: 173






« Reply #1 on: May 09, 2009, 03:55:05 PM »

One more thing...

I'm releasing result at the end of the method to avoid memory leaks, is it correct to be doing this after I return result. At this point in the text is that the correct way to release result? Am I correct that I can't access it to release it within main and it is a "local" use of memory?
Logged
esc
Global Moderator
Full Member
*****
Posts: 230






« Reply #2 on: May 10, 2009, 05:43:12 PM »

One more thing...

I'm releasing result at the end of the method to avoid memory leaks, is it correct to be doing this after I return result. At this point in the text is that the correct way to release result? Am I correct that I can't access it to release it within main and it is a "local" use of memory?

Hi Mark,

Any statement after "return" won't be executed.  Secondly, since you are returning "result", if you "release result" before your method returns, you will essentially be returning nil from your method.

To avoid memory leak, the caller of your method can release the memory allocated, e.g.
fraction_result = [a_fraction add: b_fraction];
[fraction_result release];

But the preferred way, as noted on top of page 191, is that the method is responsible for releasing the memory by "autorelease", e.g.
id result = [[Fraction alloc] init];
[result autorelease];
The book explains this later.  At this point, chapter 9, suffice to have the caller of your method release the result.

Going back to your original post, "id" is a pointer to any type of object.  So yes, the compiler won't flag an incompatible message sent to an id object.  There is flexibility in using dynamic binding...program 9.2 is an example.

Hope this helps.
Logged
MarkReid
Full Member
***
Posts: 173






« Reply #3 on: May 12, 2009, 06:52:40 PM »

Here's my main from this program, at least the section that I have a question on...

   id dataValue1, dataValue2, result;

   Complex *cp1 = [[Complex alloc] init];
   Complex *cp2 = [[Complex alloc] init];
   Fraction *f1 = [[Fraction alloc] init];
   Fraction *f2 = [[Fraction alloc] init];
   [cp1 setReal:2.0 andImaginary: 3.0];
   [cp2 setReal:4.0 andImaginary: 2.0];

   [f1 setTo: 3 over: 5];
   [f2 setTo: 1 over: 2];
   
   dataValue1 = cp1;
   dataValue2 = cp2;
   
   result = [dataValue1 add: dataValue2];
   [result print];
   
   [cp1 release];
   [cp2 release];
   
   dataValue1 = f1;
   dataValue2 = f2;
   
   result = [dataValue1 add: dataValue2];
   [result print];
   
   [f1 release];
   [f2 release];
   [result release];

I've removed the release from the add: methods. Can you tell me if the following is correct or not please?

result is never alloc/inited in main. It is declared as an object of the id type. Would that be the equivilant to a statement like this if it wasn't an id type variable?

Fraction* result;

Meaning in that in both cases result is just a pointer to memory?

As the memory is alloc/inited within the add: method and that is assigned to result, that means the memory location used by the add method is the same location pointed to by the result variable? So that's why when I release result it clears the memory?

If that's the case am I correct in thinking that I should be releasing result after each print method is called. If not the second add: method call creates a second memory location for an object but the first is not able to be release because nothing now refers to it?

I am sorry there are so many questions, I really appreciate you helping me understand this better.
Logged
skochan
Administrator
Hero Member
*****
Posts: 3103







« Reply #4 on: May 12, 2009, 07:50:50 PM »

Quote
result is never alloc/inited in main. It is declared as an object of the id type. Would that be the equivilant to a statement like this if it wasn't an id type variable?

Fraction* result;

Meaning in that in both cases result is just a pointer to memory?

Yes, the fact that the id type doesn't use  the * I think adds to the confusion here.  (id is actually a typedef, which is discussed in Chapter 10.  Take a look at the example for the NumberObject typedef there).

Quote
As the memory is alloc/inited within the add: method and that is assigned to result, that means the memory location used by the add method is the same location pointed to by the result variable? So that's why when I release result it clears the memory?

Yes!   Wink

Cheers,

Steve
Logged
MarkReid
Full Member
***
Posts: 173






« Reply #5 on: May 13, 2009, 02:44:48 AM »

Thank you Steve, that helps a lot.

For the last part of my original question, am I correct in thinking that I should be releasing result after each print method is called. If not the second add: method call creates a second memory location for an object but the first is not able to be release because nothing now refers to it?
Logged
skochan
Administrator
Hero Member
*****
Posts: 3103







« Reply #6 on: May 13, 2009, 03:58:19 AM »

Sorry, I missed that.  Yes, you are correct in the conclusion that it should be released.

Cheers,

Steve Kochan
Logged
Pages: [1]   Go Up
Print
Jump to:  



Login with username, password and session length

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Entire forum contents (c) 2009 classroomM.com. All rights reserved.