Calling super init


#1

self = [super init];

Calling “init” in the super class of Appliance means calling “init” in NSObject. If init returns a pointer to an object of the class that created it, doesn’t that mean that the object created is an instance of NSObject? “self” is in “Appliance.m”. How can you assign an NSObject instance to “self” in Appliance.m?


#2

No, the object returned from [super init] is an instance of Appliance.

Remember that the way it is called is:

Appliance *a = [[Appliance alloc] init];
That is, the alloc is sent to the class Appliance, which allocates an instance of Appliance. Then init is sent to that instance of Appliance. [super init] runs NSObject’s init, but it is run on an instance of Appliance.


#3

That makes sense. Thanks for the prompt reply, Aaron. Love your book. Will be starting the iOS book next.


#4

When we do this:

  • (init)
    {
    self = [super init];
    voltage = 120;
    return self;
    }

the only real change is voltage=120; right?..I mean, the rest is just the init method defined in NSObject…so…why do we need to write self=[super init]; and return self; again??..

…I mean, isnt that the default init already?


#5

oh…I see, it’s because of the deviant init methods…


#6

I apologise if this makes sense to everyone but me, however I’d be failing myself if I didn’t pursue this question.

Whilst the self = [super init]; runs within Appliance’s init method, i can’t understand why this is done if, as was stated, super init returns a pointer to the parent object. Hasn’t this just instantiated and initialized an NSObject?

:frowning:


#7

I’ve been trying to get my head around this and I’m getting more confused - not helped by the Apple documentation,

So i have a class ShoutingPerson that inherits from Person that in turn inherits from NSObject.

If my init methods in ShoutingPerson and Person set self = [super init], ultimately won’t the self ‘object’ refer to the NSObject and not the ShoutingPerson.

I know I’m wrong but I need a clearer explanation of how this works… please.

Tony


#8

Hi Tony,

I think you’re getting confused with why we are called super.

If we did not call super - we would have to initialize our init every time an instance of Appliance calls it - this is because NSObject’s init is always zeroed-out. Nil. So,
we override it and give it a non-nil value. So our initilazer enters the world already assigned a value.

I hope this makes sense.

The part in Aaron’s book that cleared this understand for me is:

[quote] A basic init method
In some cases, an initial value of zero for your instance variables may work fine. In others, however, you’ll need instances of your class to come into the
world with their instance variables initialized to non-zero values.
Let’s say that every instance of Appliance should start its life with a voltage of 120. In Appliance.m, override NSObject’s init method by adding a new implementation of init.[/quote]


#9

why self is not an instance of NSObject during the self = [super init] is a mystery to me. The explanation that says " the object returned from [super init] is an instance of Appliance" because " [super init] runs NSObject’s init, but it is run on an instance of Appliance" doesn’t make sense to me. I understand the just use the convention approach and move on but I’m hoping to understand this more fully.

can we initialize like this:

-(id)init { (id) foo = [super init]; voltage = 120; return foo; }

setting self to the returned instance of NSObject is confusing. It seems like NSObject’s instance shouldn’t be set to self because self is the instance of the current class Appliance.


#10

The reason we do the assignment self = [super init] in the init method is to allow for the possibility that the super class might change the instance (yes this can happen depending on the what the super class does) to a new instance of the class that the init method belongs. Therefore, it makes sense to do the assignment (and even to access the instance variable by self->anIvar.)

By the way, I like the name foo! And here comes the FooBar.

Now imagine this:

@interface FooBar: Bar
{
    double _voltage;
}
@end

@implementation FooBar
- (id)init
{
     id foo = [super init];
     // foo->_voltage = 240; // error
     return foo;
}
@end

First thing to note here is that we can’t assign a value to the _voltage attribute because the type of foo is id. id is a terrible but a very useful type!

Also to note is that the name foo does not matter. What matters is the value being returned, which is an instance of FooBar. We could have replaced id foo by self and return foo by return self, and the code would be the same.

But to assign a value to the _voltage attribute, we need to get rid of foo (the replacement for self in above code), and use self instead:

- (id)init
{
    self = [super init];
    self->_voltage = 240;  // same as _voltage = 240
    return self;
}

- (void)reconfigure
{
    self->_voltage = 120; // same as _voltage = 120
}

self is a predefined variable whose type depends on the class type in the implementation section of the class, and it can be assigned to only in a method in the init family.

Finally, [super init] does not return a pointer to the instance of the super class; it returns a pointer to an instance of the class on which the alloc method was invoked (the alloc creates the instance.)

@interface FooBar: Bar
...
@end

FooBar *fooBar = [[FooBar alloc] init];
...
- (id)init
{
    self = [super init];  // self is an instance of FooBar, not an instance of Bar!
    ...
    return self;
}

#11

Very interesting stuff (ok, I’m a nerd!). You say “it returns a pointer to an instance of the class on which the alloc method was invoked.” That is what Aaron was saying earlier - it just didn’t sink in. Let me ask you this…

English Translation: send alloc message to Appliance. Alloc method not in class Appliance! Look in Appliance’s superclass NSObject. I found alloc. Now go reserve the memory and return the address to the caller ([Appliance alloc] ?Is NSObject instantiated at this point?). Time to init! Send message init to the object that was just created called appliance (notice lower case). I found init in appliance object but I’m going to send init to appliances superclass which is the NSObject instance just created. Zero out the NSObject variables and return a pointer to the class on which the alloc method was invoked (the appliance object!). Am I getting this right?