mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-24 20:00:37 +00:00
4.5 KiB
4.5 KiB
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:
- Why call the superclass init method?
- The current object has an isa pointer; the isa pointer is set through the superclass's init.
- You need to ensure that the superclass's properties are also initialized.
- Pattern for overriding init:
-(instancetype)init{
if (self = [super init]) {
// todo: custom property initialization
}
return self;
}
// 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;
}
// 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.


