實例類型(instance)是oc語言中新添加的一個返回類型,實例類型作為方法返回的實例的類型,是蘋果在2013年的年度大會上宣布的。這個新添加的實例類型不僅可以用來作為oc方法的返回類型,且能用這個實例類型來作為向編譯器的提示,提示方法返回的類型將是方法所屬類的實例。
類的實例,作為方法返回類型,宜采用關鍵字instancetype作為方法的返回類型,如alloc,init和類工廠方法等。使用instancetype作為類(或者類的子類)的實例返回類型,可以大大改善oc代碼的類型安全。例如,考慮下面代碼:
@interface MyObject : NSObject
+ (instancetype)factoryMethodA;
+ (id)factoryMehtodB;
@end
@implementation MyObject
+ (instancetype)factoryMehtodA {
return [[[ self class] alloc]init];
}
+ (id)factoryMehtodB {
return [[[self class]alloc]init];
}
@end
void doSomething() {
NSUInterger x,y;
x = [[MyObject factoryMehtodA] count];
y = [[MyObject factoryMethodB] count];
}
通過以上的代碼可以看到,instancetype作為+factoryMethodA的返回類型,也就是說,該消息的類型表達式是MyObject* 。danshi MyObject由于先天缺乏一個-count方法,編譯器將會對此給出一個關于x行的警告。對于這樣的情況,如果把instancetype換成id作為實例的方法返回類型,也就是如上面代碼的實例,id作為方法+factoryMethodB的返回類型。在編譯器編譯的過程中不會發出關于y行的警告。
為什么編譯器沒有發出沒有給出警告?因為id類型的對象可以作為任何類,并且調用的方法-count在一些類中存在,故此向編譯器發出方法+factoryMethodB返回值事項了-count的信息,從而編譯器沒有給出警告。對于該種編寫代碼的方法,在無形中埋下了隱患。
為了確保instancetype工廠方法有正確的子類行為,一定要使用[self class]分配類,而不是直接飲用類名。遵循這個慣例,記住,務必要使編譯器能正確地推斷出子類類型。例如,依據前面的示例,考慮嘗試做一個前面MyObject子類示例:
@interface MyObjectSubClass : MyObject
@end
void doSomethingElse () {
NSString * aString = [MyObjectSubclass factoryMethodA];
}
對于上述代碼,編譯器將會發出警告。
在該示例中,+factoryMethodA消息發送之后,將返回一個類型MyObjectSubClass的對象實例。編譯器就能恰當的確定+factoryMehtodA的返回類型應該是子類MyObjectSubClass,而不是工廠方法中所聲明的超類。
在編寫代碼中,通常在處理init方法和類工廠方法時,宜用instancetype類替換id作為返回值。在新版的Xcode5中,雖然,編譯器會自動地把alloc,init,new方法之中的id轉換為instancetype類型,但對于這幾種方法之外的其他方法,編譯器則不會進行轉化。在oc的公約之中,明確地建議對所有方法盡可能的使用isntancetype。也就是說,作為返回值,id由于自身的缺陷,會在oc中逐漸退出,由isntancetype來代替。
注意,僅有在作為返回值的時候,宜用instancetype來替換id。而不是代替代碼中的所有的id。與id不同,instancetype關鍵字僅能作為方法聲明的返回類型。也即是說,在某一特定卻與,isntancetype可以代替id。并不是所有區域都可以代替。
要點######
(1)instancetype僅僅用來作為oc方法的返回類型.
(2)使用instancetype可避免隱式轉換id而造成的欺騙性編譯無誤通過的現象,防止程序正式運行時候出現崩潰現象。可以大大改善oc代碼的類型安全。
(3)在某一特定區域,instancetype可以替代id,并不是所有區域都可以替代id。