看透Objective-C構造方法

構造方法

  • new方法的內部就是先調用alloc方法,再調用init方法測試

    • alloc方法:那個類接受alloc消息,那麼該方法返回該接受類的對象,並把對象返回指針

    • init方法:是1個對象方法,做用:初始化對象code

  • 建立對象的步驟:先使用alloc建立1個對象,再使用init初始化這個對象,纔可使用這個對象對象

    • 使用1個未被初始化的對象是很危險的
  • init方法:做用:初始化對象,爲對象賦初始值,叫作構造方法編譯器

重寫init構造方法

  • 若是想建立出來的對象的屬性值不是默認的初始化值,則須要重寫init方法it

  • 重寫init方法的規範:io

    • 必需要先調用父類的init方法(由於當前類初始化就是經過`[父類init]`去初始化),而後將返回值賦值給self編譯

    • 調用init方法有可能會失敗,若是失敗直接返回nilimport

    • 判斷父類是否初始化成功。若是self != nil,則表明初始化成功方法

    • 若是初始化成功就去初始化當前對象的屬性

    • 最後返回self

解惑:

  1. 爲何要調用父類的init方法?
    1. 當前類有isa指針,當前類的isa指針賦值是經過父類的init方法賦值的。
    2. 須要保證當前對象的父類屬性同時被初始化
  2. 重寫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];

init

init

關於「自定義構造方法必須以initWith開頭」作個實驗

initwith

報錯信息很明顯:不能在構造方法以外給self賦值

由於,編譯器認爲只有以initWith開頭的方法是構造方法

相關文章
相關標籤/搜索