Understanding the init syntax - objective-c

I've read quite a few different posts about overriding the init method hoping to find answers for a couple of syntax questions I've been unable to figure out.
(id) init
{
self = [super init];
if(self){
}
return self;
}
So when we send the init method to the superclass of our subclass (let's assume superclass is NSObject) we are initializing all the instance variables inherited from the superclass? What else does this accomplish?
Whenever we create a new class, are we always inheriting instance variables from the parent class? For instance if I create a class called Fraction...
Fraction : NSObject
Fraction * myFrac = [[Fraction alloc] init]
Does the object that myFrac is referencing automatically inherit instance variables that I haven't even declared yet from the parent class?
Lastly when doing
self = [super init];
Aren't we initializing the superclass? What exactly are we storing in self? Is the result of init a pointer to our newly initialized object of our subclass?
I know this has been asked quite a few times, but I couldn't find these answers in the explanations. Sorry for the pileup of questions.

So when we send the init method to the superclass of our subclass
(let's assume superclass is NSObject) we are initializing all the
instance variables inherited from the superclass?
By default all ivars are set to nil/NULL/0/0.0/NO, depending on their type, yet your parent class may want to have them set to something else by default, in that case it will change their value in its init method.
What else does this accomplish?
Whatever NSObject (or your parent class) wants to do when a new object is initialized. Basically the convention says, you must not use an object that has not been initialized (with the exception of release - you may release an object that has never been initialized, that is explicitly allowed). Most other languages know the concept of contsructors, e.g. in Java you'd say new String(...) to create a string object, which does two things: It creates a new string object and it initializes the object by calling its constructor. Java will not allow you to do one thing without doing the other one. In Obj-C these two things are individual steps. alloc creates a new object and init initializes it. Offering two separate steps has advantages in some cases, but it also has the disadvantage that you must rely on conventions (init must be called before the object may be used, yet it must never be called more than once; the compiler will enforce neither one, though, at least not last time I checked that).
Whenever we create a new class, are we always inheriting instance variables from the parent class?
Yes; unless NSObject doesn't have any. Most ivars in Obj-C are private, protected is already a huge exception and you hardly ever see public ones. So basically you should never directly access the ivar of your parent class and thus you don't really have to care if you inherit any or none.
self = [super init];
Aren't we initializing the superclass? What exactly are we storing in
self? Is the result of init a pointer to our newly initialized
object of our subclass?
An init method is allowed to return a different object than the one the method has been called for. E.g. the following is valid:
static MyClass * ThereIsOnlyOneIstance;
- (id)init
{
if (ThereIsOnlyOneInstance) {
[self release];
return [ThereIsOnlyOneInstance retain]; // Without retain if using ARC
}
self = [super init];
if (!self) return nil;
ThereIsOnlyOneInstance = [self retain]; // Just `= self` if using ARC
return self;
}
The following two if-statements will be true:
MyClass a = [[MyClass alloc] init];
MyClass b = [MyClass alloc];
if (a != b) NSLog(#"a != b will be true");
b = [b init];
if (a == b) NSLog(#"Now a == b will be true");
Also an init method may fail, in which case it must release the object and return nil. So when calling [super init] this method may fail. Don't think too much about why it may fail, just keep in mind that it may fail. Now assume that you write the following code:
- (id)init
{
[super init]; // BAD!!! THIS IS BROKEN!!!
// Recent versions of CLANG will even make this
// a hard compiler error and refuse to compile that.
return self;
}
If [super init] failed, the object has been released and nil was returned, but you haven't updated self, you just return whatever value used to be in self prior to calling [super init]. As a result, you return a pointer to a dead object, since at the memory location self points to is no object any longer, this is a dangling pointer and using it can cause your app to crash or otherwise malfunction.
That's why you always must write the output of another init method back to self. Same is true for calling init from outside. The following code is broken:
MyClass x = [MyClass alloc];
[x init]; // BAD!!! THIS BROKEN!!!
It is broken, since init may release the object x points to, so x is now a dangling pointer. You always must capture the output of init back to the variable that should point to the object. The following code is correct:
MyClass x = [MyClass alloc];
x = [x init];
Though usually you alloc/init in just one combined call, of course:
MyClass x = [[MyClass alloc] init];
but that's actually the same, the compiler generated code will look no different than before.

So when we send the init method to the superclass of our subclass
(lets assume superclass is NSObject) we are initializing all the
instance variables inherited from the superclass? what else does this
accomplish?
No. The runtime initializes all variables in an Objective-C context to nil for you (rather than a garbage value without explicit initialization under the C and C++ runtimes). -init exists for setup, and it actually unnecessary for direct subclasses of NSObject, as the default -init method returns self and exits. That said, -init and those methods in its family are often necessary to initialize the member variables and setup state of objects further down the inheritance chain. Don't think of it as a companion to +alloc, rather just a handy setup method that's become the norm in the language.
Does the object that myFrac is referencing automatically inherit
instance variables that I haven't even declared yet from the parent
class?
If by "inherits" you mean that any variables you create still maintain the offset that their superclass hands them, then yes. If by "inherits" you mean "gives access to", then it depends. The #public, #private, and #protected directives determine the access rights a derived class gets to the instance variables of its parents.
Aren't we initializing the super class?
Yes, but understand that init and friends do not actually allocate memory, or setup anything language-specific. They just setup, hand off self, and walk away.
What exactly are we storing in self?
We're storing the object allocated by +alloc and returned to us by NSObject in the form of self. Calling through to super just gives the superclass an opportunity to run its setup, then pass us back a self pointer so we can do our setup.
Is the result of init a pointer to our newly initialized object of our subclass?
Oh, I sure hope so.

Related

If I do nothing in -init, is it the same as just calling [MyClass alloc]?

If I have an NSObject subclass which either has no -init method or simply does nothing in -init, is there any difference between an instance created these two ways:
MyClass *instance = [MyClass alloc];
MyClass *instance = [[MyClass alloc] init];
By "does nothing in -init" I mean
- (id)init {
self = [super init];
if (self) {
}
return self;
}
Since NSObject's -init method itself does nothing, I can't see there being any difference, but of course the advice is that you must call -init to properly prepare an object.
Here's the snippet from NSObject's -init method which got me wondering about this:
The init method defined in the NSObject class does no initialization; it simply returns self.
If I have an NSObject subclass which either has no -init method or
simply does nothing in -init, is there any difference between an
instance created these two ways:
MyClass *instance = [MyClass alloc];
MyClass *instance = [[MyClass alloc] init];
Technically, there is no difference.
But that doesn't mean you should use a bare +alloc to ever create an instance for a variety of reasons.
First, it is the principal of the thing. Objective-C coding standards say +alloc should always be followed by -init.
Secondly, it is all about consistency and code maintenance. What happens when you refactor MyClass to be a subclass of some class where the designated initializer is actually critical? A nasty, hard to figure out, bug is what happens.
Of relevance, note that the use of +new has been all but deprecated for a similar reason. It makes refactoring tedious (dammit! gotta break apart THIS call site, too!) and the convenience factor is exceedingly minimal.
No, it's not and you're not doing nothing, you're calling [super init] and that does a lot to initialize your superclasses up until NSObject.
You can do it in theory.
When you want to create an instance, you can do it simply using the alloc method, so this code is perfectly accepted:
NSObject *someObject = [NSObject alloc];
What creates the instance is the alloc method, so you have created an instance of NSObject.
But if you want to use it you have to initialize it, since the NSObject init method is used by a class to make sure its properties have suitable initial values at creation (Apple documentation).
The most important thing done by the init method is to create the self variable, so if you want to use the instance created with the alloc method, you have to init it.
- (id)init {
self = [super init];
if (self) {
// initialize instance variables here
}
return self;
}
Without the initialization method you have only an unusable instance.
alloc allocates a place in memory for the instance of the object to be stored. If you’re using a local variable it is allocated on the stack, while objects (ivars etc) are allocated on the heap.
init initialises the instance of the object and points it to the allocated memory space - this is why you must always call init after alloc.
e.g.
MyClass *instance = [[MyClass alloc] init];
In your instance your init implementation is empty so it can be removed and you can let the superclass handle it. You would override init to set some state on the object itself.
You might want to take some time to read the Apple Documentation on this if you want to brush up.
Calling MyClass *instance = [MyClass alloc]; - will leave you with an invalid object. You need to allocate and initialize every object you create.
If you do it this way, all objects until MYClass will be initialised. MyClass won't though.

Self = [super init]

If self is able to store the base class instance then when we are returning the self, how it transformed to derived instance.
Here's what I think you're asking: suppose we have a base class Base and a subclass Derived. If -[Derived init] calls -[Base init] and -[Base init] returns a different instance, won't that different instance be an instance of Base and not Derived and thus inappropriate? For example, the new object won't have the instance variables that Derived might have added to the class.
The answer is that Base is not allowed to do that. If it replaces the original instance, it must do so in a manner that respects the dynamic type of that original instance. For example, it might do something like:
// Re-allocate with 100 extra bytes
id newSelf = NSAllocateObject([self class], 100, [self zone]);
[self release];
self = newSelf;
// ... continue to initialize ...
return self;
Or, it might dynamically generate a new subclass of the original class and then allocate a new instance of that new class.
NSString* newClassName = [NSString stringWithFormat:"%#_DynamicSubclass", NSStringFromClass([self class])];
Class newClass = objc_allocateClassPair([self class], [newClassName UTF8String], 0);
// ... further configure the new class, by adding instance variables or methods ...
objc_registerClassPair(newClass);
id newSelf = [newClass alloc];
[self release];
self = newSelf;
// ... continue to initialize ...
return self;
Whatever it does, it has to satisfy the constraint that the new instance is suitable to be used wherever the old instance was, based on its dynamic type.
self is a hidden method argument:
// this Objective-C
- (id) initWithString:(NSString*)str;
// gets implemented like this C function would be
- (objc_object*) Foo_initWithString(Foo* self, SEL _cmd, NSString* str);
It is a pointer to memory (allocated with alloc) that is already big enough to hold the most derived object. The most derived class calls super's init, which also calls its super's init and so each class in hierarchy gets its constructor called.
So, nothing is transformed — it is just a pointer to an already existing object, you can either return it (99.9% of the time) or substitute another object instead.
Note there is a second hidden argument, the selector _cmd, which in this case equals to #selector(initWithString:). You can also use it if you need current method name e.g. for debug logging.
Here super instance is not assigned to derived instance. self = [super init]; is simply like telling the runtime system to look for the init method to the super class method selector table... inside super -init method, the self is like support for both super class and derived class. In objective c, incase of class inheritance.. only instance variables are duplicated.. methods are shared by all classes in hierarchy. If u override.. u should do self = [super init]; this will lead u to NSObject -init method. If we override -init... methods from super class, make sure that the super -init... is called first. This is what i understand. Thank you.

Super in initializing objects [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
why does initializing subclasses require calling the super class's same init function?
I really can't understand the role of super in initializing an object.
For example, having this (example — not written by me) code:
#implementation MyObject
- (id) init
{
if([super init]){
return self;
} else {
return nil;
}
}
#end
What [super init] actually does? I'm confused, can't get the point
It is necessary to ensure correct initialisation of inherited instance variables from the super class of MyObject.
Since Objective-C is object oriented you can inherit from other classes. When you inherit from other classes you can intercept messages and get to decide if you pass them on to the class you inherit from. In the case of init it is almost always important to do self = [super init] or use the designated init method of the class to make sure the object is created correctly. Imagine if in MyObject in your init method you create an NSMutableArray that your class uses but init was never called because someone else inherited from your class and never called [super init]. You would then have nil references or either a bad pointer every where you attempted to used your NSMutableArray. The reason why it is important to set self equal to [super init] is the value of self may change such as in error recovery.
//this is valid
-(id)init
{
if((self = [super init]))
{
if(someInitializationFails)
{
[self release];
self = nil;
}
}
return self;
}
Wil Shipley recommends this (from 2009):
- (id)init;
{
if (!(self = [super init]))
return nil;
// other stuff
return self;
}
But why assign super init's return to self?
Matt Gallagher's article attempts to explain it...
-- Quote:
If you remember back at the start, I
said that the initWithString: part of
a typical [[MyClass alloc]
initWithString:#"someString"]
invocation is converted into an
objc_msgSend call:
MyClass *myObject2 = objc_msgSend(myObject1, initSelector, #"someString");
So by the time we get
to the inside of the method, self
already has a value; its value is
myObject1 (i.e. the allocated object,
as returned from the [MyClass alloc]
call. This is essential because
without it, the super invocation
wouldn't be possible — the self value
is used by the compiler to send the
invocation:
[super init];
becomes:
objc_msgSendSuper(self, #selector(init));
Yes, self already
has a value when your initializer
starts. In fact, it is almost
guaranteed to be the correct, final
value.
-- Unquote
Essentially, I think a lot of people are left confused as to what each init method's 'self' is pointing to exactly, up through the superclass chain.
The answer to this riddle is implied in Apple's Objective-C Programming Language doc, under the section titled Designated Initializers:
Note that B version of init sends a
message to self to invoke the
initWithName: method. Therefore, when
the receiver is an instance of the B
class, it invokes the B version of
initWithName:, and when the receiver
is an instance of the C class, it
invokes the C version.
Or, in other words, the 'self' variable points to the our instance that is being initialized. Again to reemphasize, all of these init methods up through the superclass chain are inherited by our instance, and as such, the 'self' variable in them points to our instance (unless explicitly changed) .
Am I right? Of course!

Why should I call self=[super init]

Let's say I create my class and its init method. Why should I call and return value of superclass init assigned to self? Which cases it covers?
I would appreciate examples why would I need it for Cocoa superclass and non-Cocoa.
You mean why
self = [super init];
rather than
[super init];
Two reasons:
in initialisation, failure is indicated by returning nil. You need to know if initialisation of the super object failed.
the super class might choose to replace the self returned by +alloc with a different object. This is rare but happens most frequently with class clusters.
Edited in response to Michael's comment:
I can understand why I need to save and return [super init]. But is it just convention and good looking makes us use self as a temporary variable to pass result along?
No. Instance variables are accessed relative to the self pointer, so in the following:
-(id) init
{
self = [super init];
if (self != nil)
{
myBoolIvar = YES;
// The above is an implicit version of self->myBoolIvar = YES;
}
return self;
}
self has clearly got to point to the right block of memory i.e. the one you are going to return.
The other point is that if super init returns different class instance then the rest of the code after that line may not even make sense, lead to memory leaks and crashes, not even talking about the object instantiated from that class.
That could be a problem. If I subclassed NSNumber and [super init] decided to return an NSString (which it could - there's nothing to stop it) that would clearly be a disaster. Whatever super returns from -init must be "compatible" with the subclass in the sense of providing space for ivars and being further subclassible or it's a horrendous bug (unless, of course, the problem is documented). So, in general, you don't need to worry about checking the class. However, do read the documentation. See for instance the section on subclassing NSString in NSString's docs.
I know it is a little bit late for my answer, but I cannot stop myself from posting a link which I found very useful in clearing my doubt about this problem.
Matt Gallagher: What does it mean when you assign [super init] to self?
EDIT: As per the comments, here are the essential points in the link
To understand why self=[super init]; we need to consider many points. Let's tackle it one by one.
What is self
Every method has two hidden parameters: self and _cmd. So the method call
- (id)initWithString:(NSString *)aString
is changed by compiler into a function call like this
id initWithString(id self, SEL _cmd, NSString *aString);
Why do we need self?
The reality is that the compiler uses the self parameter to resolve any reference to an instance variable inside a method.
Suppose that we have a method setValueToZero and value is an instance variable of the class it belongs to, then the implementation
- (void)setValueToZero
{
value = 0;
}
will be converted by the compiler into a function like this
void setValueToZero(id self, SEL _cmd)
{
self->value = 0;
}
Do self already have a value when init is called?
Following is an example of a typical object creation and initialization.
[[MyClass alloc] initWithString:#"someString"]
Here, by the time we get into the initWithString method, self will have the newly allocated object as its value (i.e., the return value from [MyClass alloc]). In fact, it is almost guaranteed to be the correct, final value.
Why self = [super init];?
It is because [super init] is permitted to do one of the three things:
Return its own receiver (the self pointer doesn't change) with inherited instance values initialized.
Return a different object with inherited instance values initialized.
Return nil, indicating failure.
In the first case, assignment has no effect on self. In the third case, the initialization has failed, self is set to nil and it is returned.
The reason behind assignment to self is with the second case. Consider the following
- (id)initWithString:(NSString *)aString
{
self = [super init];
if (self)
{
instanceString = [aString retain];
}
return self;
}
We want the conversion from
instanceString = [aString retain];
to
self->instanceString = [aString retain];
to act on the correct value and thus we have to change the value of self.
When would [super init] return a different object?
In one of the following situations
Singleton object (always returns the singleton instead of any subsequent allocation)
Other unique objects ([NSNumber numberWithInteger:0] always returns the global "zero" object)
Class clusters substitute private subclasses when you initialize an instance of the superclass.
Classes which choose to reallocate the same (or compatible) class based on parameters passed into the initializer.
In all but the final case, continuing to initialize the returned object if it changes is a mistake — the returned object is already completely initialized and isn't necessary related to your class anymore. So a better init approach will be as follows
- (id)initWithString:(NSString *)aString
{
id result = [super init];
if (self == result)
{
instanceString = [aString retain];
}
return result;
}
Conclusion
You don't need to assign [super init] to self to make most classes work. In some obscure cases, it is actually the wrong thing to do.
So why do we continue to assign to self? It's the traditional template for an initializer, and although it's wrong in some cases, it is right in other cases which have been written to expect this approach.
Basically every Objective-C class is a subclass. It's either some class you've specified or NSObject.
In the subclass (your class that you're working on) you call
self = [super init]
What this basically does is calls the super class's (the ones I mentioned above) init method (the constructor) and assigns it to the current class.
This makes sure that the superclasses' initializing method is called.
Now for
If(self)
This basically checks if the above piece of code worked.
This is done to insure that if you call some Instance Variable of the super class, you'll be able to do so.
In most cases, setting self to [super init] does nothing since [super init] will wind up returning self anyway. There are some rare cases, however, where [super init] will return something different. It may return nil if it fails to initialize the superclass for some reason or it may decide to return a completely different object.
Source
Implementing The Designated Initializer
**
self
**
Inside a method, self is an implicit local variable. There is no need to declare it, and it is automatically set to point to the object that was sent the message. (Something like this in Android programming.) Typically, self is used that an object can send a message to itself. Example here:
return self;
**
super
**
When we overriding a method, we want to keep what method of the superclass is doing and have your subclass add something new on that. To make it easier, there is compiler directive in Objective-C called super.
How does super work? Usually when you send a message to an object, the search for a method of that name starts in the object's class. If there is no such method, the search continues in the superclass of the object. The search will continue up the inheritance hierarchy until a suitable method is found. (If it gets to the top of the hierarchy and no method is found, an exception is thrown).
When we send a message to super, we are sending message to self, but the search for the method skips the object's class and start at the superclass. In the above case, we send init message to super. This calls NSObject's init method.
Because you have to initialize the object somehow, and presumably you want to do any initialization a superclass required be done, since you're descending from it.

SELF keyword in Objective-C

In a project I'm creating, I have various classes. One of my classes has an instance of NSMutableArray that holds objects of another one of my classes. I thought I had a firm understanding on this topic, but somehow it got jumbled up in my mind again.
When initializing an instance of this class, I have this initilize method:
- (MMShowMovement *) initWithMovementName: (NSString *) name andNumber: (NSInteger) number {
if( [super init] ) {
[self setMovementTitle: name];
[self setMovementNumber: number];
[self setDotArray: [[NSMutableArray alloc] init]];
}
return self;
}
Later on, after an instance of this class is created, I can add objects to the NSMutableArray "dotArray." Here is that method.
- (void) addDot: (MMDot *) dot {
[dotArray addObject: dot];
}
(I know, its simple) I'm wondering, when I use "dotArray" in this method, I am accessing the dotArray object for the instance of the class for which this method has been invoked, correct? Or should I use the self keyword here also?
- (void) addDot: (MMDot *) dot {
[[self dotArray] addObject: dot];
}
Honestly, I'm not really sure. I believe it is the former, but I'm unsure as to why. And it is not necessary to use the self keyword in this method, why do I have to use it in the initializer to access the object?
self is a pointer to the current receiver - It refers to the object that received a message.
You can use self to get access to the object that performs the current method.
In your case, this means that if object X of type MMShowMovement receives an addDot: message, self contains a pointer to X.
You can access dotArray in three different ways:
[dotArray addObject:dot]; //directly access the instance variable dotArray
[[self dotArray] addObject:dot]; //access dotArray with an accessor method
//--or--
[self.dotArray addObject:dot]; //access dotArray with an accessor method using dot-syntax
If you are using automatic KVO notifications, you have to use the accessors (instead of directly manipulating the ivar) to trigger notifications.
To ensure that a variable is accessed via its accessor method, you have to prefix self.
Usually we'll write
self = [super init]
Because super's initialization method might return an object that’s not the same as the one that was allocated. So that's why we use self in initxxx method and we don't need to use self in other kinds of methods.
I learned this stuff clearly from the book Learn Objective-C on the Mac, Chap 10 Object Initialization, Mark Dalrymple and Scott Knaster, Apress.
A excerpt from the book:
instance variables are found at a memory location that’s a fixed distance from the hidden self parameter. If a new object is returned from an init method, we need to update self so that any subsequent instance variable references affect the right places in memory.
[self dotArray] calls the "dotArray" selector (method) of the object. If there is no such method, you'll get an error. You cannot access the instance variable this way, unless it's a property and you've synthesized this getter method for it.
[dotArray addObject] simply accesses the variable and calls a built-in method that is specified by NSMutableArray.
[self setMovementTitle:], [self setMovementNumber:] and [self setDotArray:] are all method calls. You always need an object reference for method calls.
In init, you may as well have said [dotArray addObject] (after initing the variable, of course).