Objective-C中的self與LLVM Clang新引入的instancetype

咱們知道,大部分面嚮對象語言對於一個類的成員方法都有一個隱含的參數。在C++、Java、C#和JavaScript中是this,而在Objective-C中則是self。固然,因爲Objective-C++要徹底兼容標準C++,所以關鍵字不能與C++有所衝突,因此用了self。編程


可是,Objective-C中的self與C++、Java等編程語言中的還有一點不一樣——Objective-C中的self能夠用於類方法,而不只僅是成員方法,這點C++、Java等都沒法作到。好比:安全

@interface MyClass : NSObject

+ (id)createMyObject;

@end

@implementation MyClass

- (id)init
{
    self = [super init];
    
    NSLog(@"Hello, world");
    
    return self;
}

+ (id)createMyObject
{
    MyClass *mc = [[self alloc] init];
    
    return [mc autorelease];
}

@end

咱們看到,上述代碼片斷中MyClass類的createMyObject類方法中經過self來調用NSObject的類方法alloc。這裏,self指向了createMyObject這個消息所發送給的類。當咱們用[MyClass createMyObject]這句語句時,createMyObject中的self其實就指示了MyClass類自己。所以,能夠直接用self來調用類方法alloc。框架


而後利用這個特性,咱們結合LLVM Clang新引入的instancetype能夠編寫出兼容性更強,更靈活方便的工廠方法。下面先介紹一下instancetype編程語言


instancetype其實跟id差很少,可是它跟id不一樣的是,它表示一個與當前類相兼容的類型,而id則是一個通用的Objective-C對象類型引用類型。所以,若是咱們要在一個類方法中返回類型爲自身類型的對象,那麼返回類型能夠寫instancetype。而上述代碼片斷徹底符合這個要求,所以咱們能夠作以下改寫:this

@interface MyClass : NSObject

+ (instancetype)createMyObject;
- (void)dummyMethod;

@end

@implementation MyClass

- (id)init
{
    self = [super init];
    
    NSLog(@"Hello, world");
    
    return self;
}

+ (instancetype)createMyObject
{
    MyClass *mc = [[self alloc] init];
    
    return [mc autorelease];
}

- (void)dummyMethod
{
    
}

@end

這樣一來,咱們若是這麼用:[[MyClass createMyObject] dummyMethod]會很是安全。由於createMyObject方法所返回的對象可確保是與MyClass類相兼容的。spa

這裏須要注意的是instancetype只能用做爲返回類型,不容許做爲參數或用於定義臨時變量。code

咱們下面將提供一個結合self特性與instancetype特性的工廠方法:對象

@interface MyClass : NSObject

+ (instancetype)createMyObject;
- (void)dummyMethod;

@end

@interface MySubClass : MyClass

@end

@implementation MyClass

- (id)init
{
    self = [super init];
    
    NSLog(@"Hello, world");
    
    return self;
}

+ (instancetype)createMyObject
{
    MyClass *mc = [[self alloc] init];
    
    return [mc autorelease];
}

- (void)dummyMethod
{

}

@end

@implementation MySubClass

- (id)init
{
    self = [super init];
    
    NSLog(@"Hi, world!");
    
    return self;
}

- (void)dummyMethod
{
    NSLog(@"I am a child.");
}

@end

你能夠調用[[MySubClass createMyObject] dummyMethod],能夠看看輸出結果。blog


此時,你會有個疑問,我直接用MyClass *myObj = [[MySubClass alloc] init];不也同樣能夠嘛,須要那麼複雜嗎?接口

固然,C++、Java等編程語言都是這麼作的。而Objective-C目前有兩種狀態,一種是MRC(Manual Reference Count),另外一種是ARC(Auto Reference Count)。這兩種模式對於實例建立而言是不同的。前者建立完了以後,須要調用release,然後者則不須要。所以,咱們經過上述講解的經過類方法來建立autorelease對象來有效地屏蔽應用層接口的統一性問題。咱們看到Apple本身在iOS7.0開始可用的框架都大量用了此種方法。這樣,經過模版自動生成出來的代碼不論是在MRC下仍是在ARC下都能正常工做。

相關文章
相關標籤/搜索