在Apple發佈Xcode7的時候,不只把Swift編程語言升級到了2.0版本,並且還對Objective-C作了許多提高,包括引入__nonnull/__nullable。其中,對於Objective-C編程語言自己而言,更爲有用的即是輕量級泛型。程序員
其中,比較明顯的體現就是NSArray、NSDictionary這些容器類都採用了新引入的輕量級泛型。經過輕量級泛型,咱們能夠很是容易地獲取其中的元素,並訪問其相印特有的屬性和方法。咱們舉一個簡單例子來闡明輕量級線程帶來的方便:express
// 不帶泛型的狀況 NSArray *numArray = @[@10, @20, @30]; int sum = [(NSNumber*)numArray[0] intValue] + [(NSNumber*)numArray[1] intValue] + [(NSNumber*)numArray[2] intValue]; // 使用泛型的狀況 NSArray<NSNumber*> *numArray = @[@10, @20, @30]; int sum = [numArray[0] intValue] + [numArray[1] intValue] + [numArray[2] intValue];
咱們經過上述例子就能看到輕量級泛型帶來的語法上的便利性,即它是一塊甜美的語法糖(syntax sugar)。編程
以前Apple LLVM 6.0對C11標準的泛型——generic selection在Objective-C上支持得還不夠良好,但Apple LLVM 7.0上已經能完美支持了。好比下述例子:編程語言
int flag = _Generic(@100, NSNumber*:1, NSString*:2, int:3, default:0); NSLog(@"The flag is: %d", flag);
上述代碼將成功地輸出「The flag is: 1」。ide
與C11的generic selection所不一樣的是,Objective-C自帶的泛型其本質爲covariant type,即協變類型。也就是,其泛型與Java的有些相似。它要求泛型必須是一個Objective-C類類型,即至少爲id類型。對於上述NSArray的例子,咱們在聲明一個Objective-C對象引用時,經過在類名後面添加<NSNumber*>來指明當前NSArray裏的元素都是NSNumber*類或其子類類型。這樣,咱們在訪問其元素時可直接訪問其intValue方法。atom
下面咱們介紹如何本身定義一個泛型類。其語法描述以下:spa
@interface class_name < __covariant type_identifier > inherit_expression線程
這裏,class_name就是類名;type_identifier是類型標識符,該標識符能夠由程序員本身命名;最後的inherit_expression表示繼承某個父類以及/或實現某些協議。code
這裏引入了一個新的關鍵字——__covariant,表示後面的type_identifier是一個泛型類型。該泛型類型在聲明一個對象時進行具體指明。對象
下面舉一個具體的例子來講明如何具體使用Objective-C泛型。
@interface MyObject<__covariant T> : NSObject
{
@private
T obj;
}
@property (nonatomic, retain) T obj;
@end @implementation MyObject @synthesize obj; - (void)dealloc { if(obj != nil) [obj release]; NSLog(@"My object deallocated!"); [super dealloc]; } @end @implementation ViewController - (void)viewDidLoad { MyObject<NSNumber*> *numObj = [[MyObject alloc] init]; numObj.obj = @100; [numObj release]; MyObject<NSString*> *strObj = [[MyObject alloc] init]; strObj.obj = @"Hello, world"; [strObj release]; }
@end
上述代碼,咱們定義了一個MyObject的泛型類,其泛型標識符用T表示。隨後,咱們用該泛型T定義了一個私有對象obj,並用它做爲一個property。
隨後,咱們在viewDidLoad方法裏用MyObject<NSNumber*>聲明瞭一個對象numObj;用MyObject<NSString*>聲明瞭一個strObj對象。咱們後面能夠直接經過numObj.obj調用intValue來訪問其int值;直接經過strObj.obj來調用length方法以得到其字符串長度。