Amazon.com Widgets Chapter 10 - initializers - designated initializer
Welcome, Guest. Please login or register.
Did you miss your activation email?
November 29, 2014, 02:40:40 AM
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
| |-+ Chapter Study
| | |-+ Chapter 10 - More on Variables and Data Types
| | | |-+ Chapter 10 - initializers - designated initializer
Pages: [1] Go Down
Print
Author Topic: Chapter 10 - initializers - designated initializer (Read 3556 times)
enigmakv
Newbie
*
Posts: 37







on: September 23, 2009, 08:49:00 PM

NSObject comes with its own initializer, the init method.

When Rectangle is a subclass of NSObject, it inherits that init method.

So we want to make a new initializer with rectangle-specific values and write something like the initWithWidth:andHeight: method.

If we want to make this the designated initializer, is overriding the inherited init method the way we do it?

And if we write multiple initializers, does the implementation become a cascade of calls to each initializer until we arrive at the designated initializer?
Logged
rgronlie
Global Moderator
Full Member
*****
Posts: 212







Reply #1 on: September 24, 2009, 01:37:14 AM

Quote
If we want to make this the designated initializer, is overriding the inherited init method the way we do it?

You must override the super's designated initializer. Which in this case is init... in other cases it may not be.

Quote
And if we write multiple initializers, does the implementation become a cascade of calls to each initializer until we arrive at the designated initializer?

Do you mean multiple initializers for a single class?
i.e.
init
initWithWidth:
initWithWidth:andHeight:
initWithWidth:andHeight:andDepth:
  <-- designated initializer

If that is the case then instead of cascading, each initializer should call the designated initializer, filling in the arguments with some default values.

Ryan
Logged

Sanity: Minds are like parachutes. Just because you've lost yours doesn't mean you can borrow mine.
enigmakv
Newbie
*
Posts: 37







Reply #2 on: September 24, 2009, 11:18:43 PM

You must override the super's designated initializer. Which in this case is init... in other cases it may not be.

Do you mean multiple initializers for a single class?
i.e.
init
initWithWidth:
initWithWidth:andHeight:
initWithWidth:andHeight:andDepth:
  <-- designated initializer

If that is the case then instead of cascading, each initializer should call the designated initializer, filling in the arguments with some default values.

Ryan

Ryan,  that is exactly what I meant about the multiple initializers.

So are you saying that if someone mistakenly calls initWithWidth: and just sends a width parameter that initWithWidth: should call initWithWidth:andHeight:andDepth: and send the user's parameter and two zeros or other default values?

I am also not seeing the purpose of multiple initializers at all.  If the designated initializer is the one with the most arguments, why not use it as the ONLY initializer?  What is the purpose of writing all the other initializers if all they are gonna do is call the designated one anyway?
Logged
enigmakv
Newbie
*
Posts: 37







Reply #3 on: September 25, 2009, 12:41:05 AM

Using the examples in the book, I am trying to create a comprehensive example assuming...
1.) Rectangle is an NSObject object
2.) I am creating the designated initializer setWithWidth:andHeight:
3.) I am overriding the init method in the Rectangle object so it will call my designated initializer.
4.) Square is a Rectangle object
5.) Square will have a designated initializer setWithSide:
6.) the init method will again be overridden to insure the square gets default value if just [Square init] is called.

If I accidently call [[Square alloc] init] instead of [[Square alloc] initWithSide: 5]...

First, the overridden init method in Square.m calls [self initWithSide: 0].
Next, in Square's initWithSide: method, the [super init] calls the init method of the Rectangle class.
That method (also overridden) in Rectangle.m calls [self initWithWidth: 0 andHeight: 0].
Now in Rectangle's initWithWidth:andHeight method the [super init] calls the init method of NSObject.

An NSObject object is created and initialized in memory and returned to the Rectangle.m setWithWidth:andHeight: method.

This method sets the Rectangle instance variables 'width' and 'height'  to zero and returns this Rectangle object to Square.m.

Square.m invokes its setSide: method with the passed default value of zero which in turn sets the 'width' and 'height' variables to zero AGAIN.


Is this the correct flow of the initialization process?  Have I left anything out?
Logged
rgronlie
Global Moderator
Full Member
*****
Posts: 212







Reply #4 on: September 25, 2009, 01:14:29 AM

In your example Square's initWithSide: should call [super initWithWidth:side andHeight:side] since initWithWidth:andHeight: is Rectangle's designated initializer. Calling Rectangle's init instead of initWithWidth:andHeight could result in a circular initialization (bad).


Here is an example I was working on:

Code: (Objective-C)
//***** Line
@interface Line : NSObject
{
  int    width;
}
@property int width;

-(id)initWithWidth:(int)w;
@end

/**********/

@implementation Line
@synthesize width;

-(id)init                                         // override super's designated initializer
{
  return [self initWithWidth:1];        // use 1 as a default for width
}

-(id)initWithWidth:(int)w
{
  if (self = [super init])
  {
    width = w;
  }
  return self;
}
@end

Code: (Objective-C)
//***** Rectangle
@interface Rectangle : Line
{
  int    height;
}
@property int height;

-(id)initWithWidth:(int)w andHeight:(int)h;
@end

/**********/

@implementation Rectangle
@synthesize height;

-(id)initWithWidth:(int)w                      // override super's designated initializer
{
  return [self initWithWidth:w andHeight:1];   // use 1 as a default for height
}

-(id)initWithWidth:(int)w andHeight:(int)h
{
  if (self = [super initWithWidth:w])         // call the super
  {
    height = h;
  }
  return self;
}
@end

Code: (Objective-C)
//***** Cube
@interface Cube : Rectangle
{
  int    depth;
}
@property int depth;

-(id)initWithWidth:(int)w andHeight:(int)h andDepth:(int)d;
@end

/**********/

@implementation Cube
@synthesize depth;

-(id)initWithWidth:(int)w andHeight:(int)h                // override super's designated initializer
{
  return [self initWithWidth:w andHeight:h andDepth:1];   // use 1 as a default for depth
}

-(id)initWithWidth:(int)w andHeight:(int)h andDepth:(int)d
{
  if (self = [super initWithWidth:w andHeight:h])  // call the super (EDIT: was passing d to andHeight:)
  {
    depth = d;
  }
  return self;
}
@end

Code: (Objective-C)
int main (int argc, const char * argv[])
{
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

  Cube *myCube = [[Cube alloc] init];
  NSLog(@"w:%i  h:%i  d:%i", myCube.width, myCube.height, myCube.depth);
  
  [myCube release];
  [pool drain];
  return 0;
}

Now you can trace through the chain of initialization with the debugger when calling [[Cube alloc] init]
Last Edit: November 20, 2009, 03:19:56 AM by rgronlie Logged

Sanity: Minds are like parachutes. Just because you've lost yours doesn't mean you can borrow mine.
enigmakv
Newbie
*
Posts: 37







Reply #5 on: September 25, 2009, 07:25:38 PM

In your example Square's initWithSide: should call [super initWithWidth:side andHeight:side] since initWithWidth:andHeight: is Rectangle's designated initializer. Calling Rectangle's init instead of initWithWidth:andHeight could result in a circular initialization (bad).

Now I am beginning to understand!  It is my responsibility to look into a class that I am going to subclass and suss out and use the designated initializer only.  But that takes me back to my original lack of understanding why there would EVER be more than one initializer in a class.  It seems like a waste of time and space to have initWithWidth:, initWithWidth:andHeight:, initWithWidth:andHeight:andDepth, initWithWidth:andHeight:andDepth:andOrigin: etc and then tell potential users of the class to only use initWithWidth:andHeight:andDepth:andOrigin.

Your example was fantastic and at least cleared up the usage questions I had.  Thanks for all the help Ryan.
Logged
rgronlie
Global Moderator
Full Member
*****
Posts: 212







Reply #6 on: September 26, 2009, 12:28:51 AM

 
Quote
But that takes me back to my original lack of understanding why there would EVER be more than one initializer in a class.

Off the top of my head, I can't think of a reason why you would have so many initializers in one class.

I could see however, at some point you may want to override the initializers inherited from the parent classes. Maybe you want different default values for the instance variables?

Code: (Objective-C)
@interface Cube : Rectangle
{
  int    depth;
}
@property int depth;

-(id)initWithWidth:(int)w andHeight:(int)h andDepth:(int)d;
@end

/**********/

@implementation Cube

@synthesize depth;

-(id)init
{
  return [self initWithWidth:2 andHeight:2 andDepth:2];   // use 2 as a default for width, height and depth
}

-(id)initWithWidth:(int)w
{
  return [self initWithWidth:w andHeight:2 andDepth:2];   // use 2 as a default for height and depth
}

-(id)initWithWidth:(int)w andHeight:(int)h                // override super's designated initializer
{
  return [self initWithWidth:w andHeight:h andDepth:2];   // use 2 as a default for depth
}

-(id)initWithWidth:(int)w andHeight:(int)h andDepth:(int)d
{
  if (self = [super initWithWidth:w andHeight:h])         // call the super
  {
    depth = d;
  }
  return self;
}
@end
Logged

Sanity: Minds are like parachutes. Just because you've lost yours doesn't mean you can borrow mine.
dharr19
Full Member
***
Posts: 175


Email




Reply #7 on: August 31, 2011, 08:15:58 PM

Hi,

In the code snippets below I don't override NSObject init in someClass.  So in this case would this be correct?

Code: (Objective-C)
@interface someClass: NSObject
@end

@implementation someClass
@end


@interface anotherClass: someClass
-(id) initWithSomething: (int);
@end

@implementation anotherClass
-(id) init{
          return [self initWithSomething]
}

-(id) initWithSomething{
          self = [super init];
          // other code here
}
@end
Logged
seerex
Full Member
***
Posts: 177


Email




Reply #8 on: August 31, 2011, 11:43:00 PM

Well what you do there is actually that you DO override NSObjects init method, since you use
Code: (Objective-C)
13.-(id) init{  
14.          return [self initWithSomething] 
15.}

Since someClass is a subClass of NSObject, it doesnt need to declare the method in it's interface, but when you do define it in the implementation, you actually do override the init method.

Other than that, your case is a valid one Smiley You override the parents init, and sets your own designated initializer for that class, that when calling init, you will actually call your own init method, but it is hidden from the user (hence the idea of Data Encapsulation)

- I think i'm right here, but i am by no means a master Smiley apologize if i mislead you.
Logged

Best Regards -
J.B.J
If you think i helped you could return the favor Wink

Subscribe to my channel on youtube: http://www.youtube.com/user/JBJProgramming

My apps:
- iTap Fruits (all countries)
- Toilet-Quiz (Denmark only)
- Zoo Kids (Denmark only)
- Diablo Item Database (All countries)
bpedit
Jr. Member
**
Posts: 65


Email




Reply #9 on: September 01, 2011, 09:15:59 AM

David,
When a method is called, the first class to be searched is the class of the receiver. If a match is not found the search will continue upward through successive parent classes.

So when you call for an initWithSomething of an anotherObject instance, your custom initializer will be used. When that initializer calls super, it doesn't find an init method so the search continues up to NSObject whose init will be invoked.

This custom initializer stuff seems like an "add on" kind of dealie being introduced in chapter 10 after you've been happy using just plain old init. But it is really something you should start using in almost all your custom classes. (For example, your someClass should probably have its own initializers too.)  Apple's The Objective-C Programming Language guide really helped me understand this initializer business.
Logged
seerex
Full Member
***
Posts: 177


Email




Reply #10 on: September 01, 2011, 09:20:35 AM

Ah seems like my answer was insufficient, good thing bpedit could step in Smiley

bpedit - do you recommend diving into the apple documentation? if so, where do one start? Smiley i hear there are thousand of pages. :O

thanks
Logged

Best Regards -
J.B.J
If you think i helped you could return the favor Wink

Subscribe to my channel on youtube: http://www.youtube.com/user/JBJProgramming

My apps:
- iTap Fruits (all countries)
- Toilet-Quiz (Denmark only)
- Zoo Kids (Denmark only)
- Diablo Item Database (All countries)
dharr19
Full Member
***
Posts: 175


Email




Reply #11 on: September 01, 2011, 09:55:04 AM

Thanks to everyone Smiley  I have started reading Apples The Objective-C Programming Language and haven't read very far yet but am learning alot.

I found this article listed below. The article was introduced in one of the answers to a questions posed in this forum.  Since you guys have a pretty good grasp already you may find this interesting.  It may be outdated though since it was written in 2009.

http://cocoawithlove.com/2009/04/what-does-it-mean-when-you-assign-super.html


Cheers
David
Last Edit: September 01, 2011, 10:25:15 AM by dharr19 Logged
bpedit
Jr. Member
**
Posts: 65


Email




Reply #12 on: September 01, 2011, 10:57:20 AM

seerex,

For now the best ancillary reading is The Objective-C Programming Language.

 Steve's book will introduce you to more documentation later. Most of Apple's documentation concerns using the frameworks which you don't cover until after learning some Obj-C. Once you do get to the second section of the book, take advantage of the many guides Apple offers as well as the technical class references to which the text introduces you.
Logged
seerex
Full Member
***
Posts: 177


Email




Reply #13 on: September 01, 2011, 12:34:07 PM

Thank you bpedit, i'll keep diving into the book Smiley
Logged

Best Regards -
J.B.J
If you think i helped you could return the favor Wink

Subscribe to my channel on youtube: http://www.youtube.com/user/JBJProgramming

My apps:
- iTap Fruits (all countries)
- Toilet-Quiz (Denmark only)
- Zoo Kids (Denmark only)
- Diablo Item Database (All countries)
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.