看透構造方法

構造方法

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

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

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

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

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

重寫init構造方法

  • 如果想創建出來的對象的屬性值不是默認的初始化值,則需要重寫init方法

  • 重寫init方法的規範:

    • 必須要先調用父類的init方法(因爲當前類初始化就是通過`[父類init]`去初始化),然後將返回值賦值給self

    • 調用init方法有可能會失敗,如果失敗直接返回nil

    • 判斷父類是否初始化成功。如果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開頭的方法是構造方法

發佈了42 篇原創文章 · 獲贊 6 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章