構造方法
new方法的內部就是先調用alloc方法,再調用init方法
alloc方法:那個類接受alloc消息,那麼該方法返回該接受類的對象,並把對象返回
init方法:是1個對象方法,作用:初始化對象
創建對象的步驟:先使用alloc創建1個對象,再使用init初始化這個對象,纔可以使用這個對象
- 使用1個未被初始化的對象是很危險的
init方法:作用:初始化對象,爲對象賦初始值,叫做構造方法
重寫init構造方法
如果想創建出來的對象的屬性值不是默認的初始化值,則需要重寫init方法
重寫init方法的規範:
必須要先調用父類的init方法(因爲當前類初始化就是通過`[父類init]`去初始化),然後將返回值賦值給self
調用init方法有可能會失敗,如果失敗直接返回nil
判斷父類是否初始化成功。如果self != nil,則代表初始化成功
如果初始化成功就去初始化當前對象的屬性
最後返回self
解惑:
- 爲什麼要調用父類的init方法?
- 當前類有isa指針,當前類的isa指針賦值是通過父類的init方法賦值的。
- 需要保證當前對象的父類屬性同時被初始化
- 重寫init方法的規範:
-(instancetype)init{
if (self = [super init]) {
//todo:自定義屬性的初始化
}
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
//測試
Person *p1 = [[Person alloc] init]; //p1.name = "杭城小劉",p1.age =22;
Person *p2 = [Person new]; //p2.name = "杭城小劉",p2.age =22;
如果2個類的關係爲組合關係,且它的一個屬性是另一個類的對象,那麼當該類初始化的時候默認它的屬性爲nil,那麼如何初始化?
-(instancetype)init{
self = [super init];
if (self) {
self.name = @"lbp";
self.age = 22;
self.pig = [[Pig alloc] init];
}
return self;
}
//測試
Person *p1 = [[Person alloc] init]; //p1.dog != nil
自定義構造方法
現狀:雖然每次雙肩的對象的屬性值不是默認的,但是每次初始化的對象的值都是一樣的。
需求:每次實例化的對象的屬性值由調用者決定
解決辦法:自定義構造方法
自定義構造方法規範:
自定義構造方法的返回值爲instancetype
方法的命名必須以initWith開頭
方法的實現類似init的實現
注意:此時不能使用new來調用。(因爲new的實現是先alloc再init,默認init的實現是給屬性賦默認值)
-(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;
}
//不能在構造方法之外給self賦值
//編譯器認爲只有以initWith開頭的方法是構造方法
-(instancetype)initWithName:(NSString *)name andAge:(int)age{
if (self = [super init]) {
self.name = name;
self.age = age;
}
return self;
}
@end
//測試
Person *p1 = [[Person alloc] init];
Person *p2 = [Person new];
Person *p3 = [[Person alloc] initWithName:@"杭城小劉2號" andAge:23];
關於“自定義構造方法必須以initWith開頭”做個實驗
報錯信息很明顯:不能在構造方法之外給self賦值
因爲,編譯器認爲只有以initWith開頭的方法是構造方法