mistake in Kochan's book, Programming in Objective-C?

Discussion in 'Mac Programming' started by OlyaGracheva, Jan 10, 2009.

  1. OlyaGracheva macrumors newbie

    Joined:
    Oct 17, 2008
    #1
    Hi there!

    I'm at page 346 in Stephen Kochan's brilliant book, "Programming in Objective-C". I will appreciate very much if someone can clarify the following for me:

    The interface file, Addressbook.h declares a method called initWithName:

    -(AddressBook *) initWithName: (NSString *) name;

    I understand this method to return a pointer to an instance of AddressBook.

    However, on the implementation file, Addressbook.m it reads:

    -(id) initWithName: (NSString *) name
    {
    self = [super init];
    if (self) {
    bookName = [[NSString alloc] initWithString: name];
    book = [NSMutableArray alloc] init];
    }

    return self;
    }

    I have two questions regarding the definition of initWithName:

    First, why is it defined as returning an id and not an pointer to an instance to an Addressbook?

    Second why do we have to initialise super?

    Many thanks in advance.

    Olya
     
  2. crackpip macrumors regular

    Joined:
    Jul 23, 2002
    #2
    I am no expert, but as I learn, I feel it is sometimes good to put yourself out for others to correct/make fun of/whatever. So here goes...

    1) type (id) is a generic type representing any object pointer. Instead of requiring all types to be specified during compile time like a statically typed language, it allows the actual type of objects returned to be determined at runtime.

    2) Your AddressBook class inherits methods and data from a chain of parent classes (usually termed super classes) up to NSObject. When you write an init method, you need to prepare the data that you added when you created the subclass, but you also need to 'init' the data defined in each parent class.

    The easiest way to do that is to call [super init] which calls the class method init for the super class. If you looked at the init method in the super class, you would find that it would also call [super init]. In this way, the 'init' message proceeds up the inheritance chain to NSObject.


    So for any real experts out there, am I correct? Am I missing deeper details?

    crackpip
     
  3. rrr macrumors member

    Joined:
    Jan 17, 2004
    #3
    You are correct, crackpip.

    super isn't an object, it's the superclass of AddressBook. It's common practice, when overriding init methods in a subclass to call the init method of the super class, so that anything that needs to get done in the superclass init will get done. (The init of the superclass will call the init of its superclass, and on and on, usually up to a root class, like NSObject.)
     
  4. OlyaGracheva thread starter macrumors newbie

    Joined:
    Oct 17, 2008
    #4
    Hi there and thanks you both for your help.

    I understand the definition of id but I guess what I was asking was, can I not just say,

    (id) initWithName: (NSString *) name;

    in the interface file instead of

    (AddressBook *) initWithName: (NSString *) name;

    ?


    I mean, why is it mentioned to be a pointer to an instance of AddressBook and later in the implementation file the method is defined to return an id type. Surely, the declaration and the definition ought to be consistent?
     
  5. toddburch macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #5
    Steve addresses this exact question earlier in the book. See page 53:

    The type id is the basis for very important features in Objective-C know as polymorphism and dynamic binding, which are extensively discussed in Chapter 9....

    Then, in Chapter 9, see the top of page 180.

    Now, from a practical standpoint, yes, (AddressBook *) could have been used in that example. You can try it to see for yourself.
     
  6. idelovski macrumors regular

    Joined:
    Sep 11, 2008
    #6
    There is explanation on page 438, second paragraph: if you subclass AddressBook then you may use that initWithName: call with subclass without typecasting.

    Something like this:

    Code:
    @interface  PlayerBook : AddressBook {
       NSString  *console;
       ...
    
    
    @implementation PlayerBook;
    
    - (id)initWithName:(NSString *)name andConsole:(NSString *)console
    {
       self = [super initWithName:name];
       ...
    If you look into NSString.h for example you'll see that all -init methods have (id) as return type. That brings us to the first question - why is initWithName: declared in interface to return (AddressBook *) type? Well, this might be a mistake. I'm not sure and now I have something to think about. ;)
     
  7. skochan macrumors regular

    Joined:
    Apr 1, 2006
    Location:
    California
    #7
    Great discussion!

    Yes, it is a mistake! :eek: It should be id in both places.

    FYI, This was corrected in the second edition of the text.

    The explanation of why you need to send the init message to super is also correctly explained. You have inherited from classes above, so you need to make sure that all those classes get a chance to do their own thing and initialize their instance variables (remember, you inherit those) and perform any other necessary initialization work for their class.


    Cheers,

    Steve Kochan
     
  8. OlyaGracheva thread starter macrumors newbie

    Joined:
    Oct 17, 2008
    #8
    Steve,

    Hi there! It's great to see you here and it's wonderful to have feedback from the great author himself.

    Secondly, thank you very much for your excellent book. It's rare to find a computing book that's, on the whole, well written and easy to understand. You've made light work of a difficult topic. I can't wait to get my hands on the latest edition of your wonderful book.

    Thank you also for your clarification regarding my questions. I had re-read chapter 9 and the section on the id type in an attempt to find whether I had missed something. I had also checked out the list of errata (error was unlisted) and so, as you can imagine, I'm mighty glad that I haven't gone crazy. :cool:

    Thank you again and also many thanks to everyone here for your support.

    Olya.
     
  9. skochan macrumors regular

    Joined:
    Apr 1, 2006
    Location:
    California
    #9
    Well, and thank you for all the compliments! :eek:

    Steve K.
     
  10. medievalone macrumors newbie

    Joined:
    Jan 15, 2009
    #10
    Another Request for Clarification.

    I am hoping the Steve is still monitoring this thread or some other kind member can point out the problem. In the iPhone Fraction Calculator of Steve's new book, the AppDelegate interface file defines a member named "window" with the following...

    IBOutlet UIWindow *window;

    The method is then synthesized in the implementation file and the window object is used in applicationDidFinishLaunching: like this...

    [window addSubview:viewController.view]
    [window makeKeyAndVisible]

    Then in the ViewController implementation file window is synthesized, sent the method makeKeyAndVisible: and released even though it is not defined in the interface file for ViewController. If these references to window are left in the implementation file, the program won't compile. Removing them allows the program to compile but once compiled and launched in the simulator, pressing the buttons on my calculator causes nothing to happen in the (label/display) although they are correctly connected.

    Do I need to define a window in the ViewController.h file or is there something else I am missing.

    In any case thanks for the book. I have learned a great deal so far.

    Kevin
     
  11. skochan macrumors regular

    Joined:
    Apr 1, 2006
    Location:
    California
    #11
    Kevin,

    I'm still here! The publisher munged some of the code in that chapter. I'll be posting an Errata page shortly (within the week I think). A preview of the errata page is posted at www.classroomM.com/objectivec. You can also look at the thread in this forum titled: "Programming in Objective-C 2.0" - Developer's Library - Stephen G. Kochan. The fixes there are spread over two posts.

    Let me know if you have any further questions, and feel free to email me at steve_kochan@mac.com.

    Cheers,

    Steve Kochan
     
  12. whooleytoo macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #12
    I'd need to see the entire interface file - but it looks like it might be missing the line to declare window as a property - synthesising a property without declaring it as a property might cause a compiler error (I'm guessing).

    Something like:

    @property (retain) UIWindow* window;
     
  13. chakuew0 macrumors newbie

    Joined:
    Apr 17, 2009
    #13
    probably not a mistake :-(

    Hi there

    Not sure if its the right place to post my stuff! It's just because here are people talking about S. Kochan's book, what is also the reason for my post.

    I'm absolutely novice in Objective-C (as also in OO) and do enjoy the clear and easy way of "Programming in Objective-C 2.0"

    Nevertheless I'm struggling with a memory allocation issue in Chapter 7. It would be great if somebody could help me understand what happens here.

    In Program 7.5 I've to take care to release the instance resultFraction

    //
    Fraction *aFraction = [[Fraction alloc] init];
    Fraction *bFraction = [[Fraction alloc] init];
    Fraction *resultFraction;

    [aFraction setTo: 1 over: 4];
    [bFraction setTo: 1 over: 2];

    resultFraction = [aFraction add: bFraction];

    [aFraction release];
    [bFraction release];
    [resultFraction release];
    //
    Ok. I've allocated resultFraction in the method <add> and therefore I need to release the memory.

    But why is is not the same in Program 7.6 ??

    //
    Fraction *aFraction = [[Fraction alloc] init];
    Fraction *sum = [[Fraction alloc] init];
    Fraction *sum2;

    n=10;
    pow2 = 2;
    [aFraction setTo: 0 over: 1];

    for (i=1; i <=n ; ++i) {
    [aFraction setTo: 1 over: pow2];
    sum2 = [sum add2: aFraction];
    [sum release];
    sum = sum2;
    pow2 *= 2;
    }

    NSLog(@"Sum= %g", [aFraction convertToNum]);

    [aFraction release];
    [sum release];

    //

    Why do I need to relese sum in the Loop and not sum2? Why is sum2 never released?

    I played with ObjectAlloc and know that the program is correct and there is no leak. But I just not understand why in 7.5 I need to relese the allocation of the fraction from the method <add>, and in 7.6 not? :confused:

    Thanks
    erwin
     
  14. skochan macrumors regular

    Joined:
    Apr 1, 2006
    Location:
    California
    #14
  15. chakuew0 macrumors newbie

    Joined:
    Apr 17, 2009
    #15
    Hi Steve
    I'm impressed :cool:
    I never thought that I would get an answer that quickly. Many thanks

    I'll join the <<classroom>> asap

    And last but not least: great book :D

    See you
    erwin
     

Share This Page