Assignment of self on if condition-Objective C
self is a hidden instance variable that points to the current object:
- (id) initWithAmount:(double)theAmount forBudget:(Budget *)aBudget{
if(self = [super init]){
budget = aBudget;
amount = theAmount;
}
return self;
}
is it similar to
this.budget=super.aBudget;
this.amount=super.theAmount;
Normally:
if(control)//true or false
{
//stmts will get executed
}
but instead of returning a true value here the self is assigned开发者_如何学Go with super. Why is it so?
Is it similar to constructor. How to use constructors(default,parameterised and copy)
in objective C?
Because an assignment expression also returns the result of the assignment,
if (self = [super init]) { ...
is equivalent to:
self = [super init];
if (self) { ...
And since if
does not just test pure boolean values but treats everything that is non-zero, non-NULL
or non-nil
as true, the if
statement tests if self
is nil
after the assignment.
When we write our own init
methods, we are supposed to assign [super init]
to self
because a init
method is free to return a different object than the receiver of the method. If we just called [super init]
without assigning it to self
, we might initialize a different object than self
, which is clearly not desirable.
This form is just the short form of the following code:
- (id)initWithAmount:(double)theAmount forBudget:(Budget *)aBudget {
self = [super init]; // you must do this, because every object inherits all properties
// from the parent class, and they must be initialized
// init can return nil if there was an error during the initialization
// so if the parents initialization failed, there is no point of initializing
// the child object
if (self != nil) {
budget = aBudget;
amount = theAmount;
}
return self;
}
It's the way initializers are defined in Objective-C. It's part of the two-stage creation pattern: seperating memory allocation and initialization of the object. As self references the object instance where the initializer resides in it has to go up the inheritance tree and set what they return to itself, after that it's your turn.
The call of super is only used in the designated initializer. You could have more initializers which should always use the designated initializer.
The pattern
- (id)init {
self = [super init];
if (self) {
// code
}
return self;
}
Is the correct way to handle failures. The test will fail if self = [super init];
returns nil: An error occured in initializers up the inheritance tree, so you don't want to use a failed initialization and skip your own code.
精彩评论