mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-24 20:00:37 +00:00
165 lines
4.5 KiB
Markdown
165 lines
4.5 KiB
Markdown
# Understanding Initializers
|
|
|
|
## Initializers
|
|
|
|
* The internal implementation of the new method is to call alloc first, then call init.
|
|
* alloc: Sends the alloc message to a class; alloc returns an instance of that class.
|
|
* init: An instance method whose role is to initialize the object.
|
|
* Steps to create an object: first use alloc to create an object, then use init to initialize it before using the object.
|
|
* Using an uninitialized object is dangerous.
|
|
* init method: Purpose — initialize the object and set initial values; this is called a constructor (initializer).
|
|
|
|
## Overriding init
|
|
|
|
* If you want the created object's properties to have values other than the default initialization values, you need to override init.
|
|
* Rules for overriding init:
|
|
* You must first call the superclass's init method (because initialization of the current class proceeds through [super init]), and assign the returned value to self.
|
|
* Calling init may fail; if it fails, return nil.
|
|
* Check whether the superclass initialized successfully. If self != nil, initialization succeeded.
|
|
* If initialization succeeded, initialize the current class's properties.
|
|
* Finally return self.
|
|
|
|
#### Clarifications:
|
|
|
|
1. Why call the superclass init method?
|
|
1. The current object has an isa pointer; the isa pointer is set through the superclass's init.
|
|
2. You need to ensure that the superclass's properties are also initialized.
|
|
2. Pattern for overriding init:
|
|
|
|
```
|
|
-(instancetype)init{
|
|
if (self = [super init]) {
|
|
// todo: custom property initialization
|
|
}
|
|
return self;
|
|
}
|
|
```
|
|
|
|
```objc
|
|
// Person
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
@interface Person : NSObject
|
|
@property NSString* name;
|
|
@property int age;
|
|
|
|
-(void)sayHi;
|
|
|
|
@end
|
|
|
|
#import "Person.h"
|
|
@implementation Person
|
|
|
|
-(void)sayHi{
|
|
NSLog(@"Hi");
|
|
}
|
|
|
|
-(instancetype)init{
|
|
self = [super init];
|
|
if (self) {
|
|
self.name = @"杭城小刘";
|
|
self.age = 22;
|
|
}
|
|
return self;
|
|
}
|
|
@end
|
|
|
|
|
|
// Test
|
|
|
|
Person *p1 = [[Person alloc] init]; // p1.name = "杭城小刘", p1.age = 22;
|
|
Person *p2 = [Person new]; // p2.name = "杭城小刘", p2.age = 22;
|
|
```
|
|
|
|
If two classes have a composition relationship and one property is an object of another class, that property defaults to nil when the containing class is initialized. How to initialize it?
|
|
|
|
```
|
|
-(instancetype)init{
|
|
self = [super init];
|
|
if (self) {
|
|
self.name = @"lbp";
|
|
self.age = 22;
|
|
self.pig = [[Pig alloc] init];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
// Test
|
|
Person *p1 = [[Person alloc] init]; // p1.pig != nil
|
|
```
|
|
|
|
## Custom initializers
|
|
|
|
* Current situation: Although each created object's properties are not the default values, every initialized object has the same values.
|
|
* Requirement: Allow callers to decide the property values when instantiating.
|
|
* Solution: Custom initializer.
|
|
* Rules for custom initializers:
|
|
* The return type should be instancetype.
|
|
* The method name must begin with initWith.
|
|
* The implementation is similar to init.
|
|
* Note: You cannot use new to call a custom initializer. (new performs alloc then init; default init assigns the default property values.)
|
|
|
|
```
|
|
-(instancetype)initWithName:(NSString *)name andAge:(int)age{
|
|
if (self = [super init]) {
|
|
self.name = name;
|
|
self.age = age;
|
|
}
|
|
return self;
|
|
}
|
|
```
|
|
|
|
```objc
|
|
// Person
|
|
#import <Foundation/Foundation.h>
|
|
@interface Person : NSObject
|
|
@property NSString* name;
|
|
@property int age;
|
|
|
|
-(instancetype)initWithName:(NSString *)name andAge:(int)age;
|
|
@end
|
|
|
|
#import "Person.h"
|
|
@implementation Person
|
|
|
|
-(instancetype)init{
|
|
self = [super init];
|
|
if (self) {
|
|
self.name = @"lbp";
|
|
self.age = 22;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
// You cannot assign to self outside of an initializer.
|
|
// The compiler treats only methods starting with initWith as initializers.
|
|
|
|
-(instancetype)initWithName:(NSString *)name andAge:(int)age{
|
|
if (self = [super init]) {
|
|
self.name = name;
|
|
self.age = age;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
// Test
|
|
Person *p1 = [[Person alloc] init];
|
|
Person *p2 = [Person new];
|
|
Person *p3 = [[Person alloc] initWithName:@"杭城小刘2号" andAge:23];
|
|
```
|
|
|
|

|
|

|
|
|
|
|
|
An experiment about "custom initializers must start with initWith"
|
|
|
|

|
|
|
|
The error message is clear: you cannot assign to self outside of an initializer.
|
|
|
|
Because the compiler considers only methods starting with initWith as initializers. |