咱們知道,大部分面嚮對象語言對於一個類的成員方法都有一個隱含的參數。在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下都能正常工做。