Objective-C隨着Xcode 7的升級帶來了許多新特性,當然此次更新最最大的就是引入了Objective-C的輕量級泛型,確切地說是Objective-C類的輕量級泛型。除此之外,還有一個小特性就是__kindof關鍵字的引入。
有些技術網站上聲稱__kindof一般用於泛型,比如:NSArray<__kindof UIView*>表示在此NSArray對象中存放的是UIView對象或UIView子類對象。不過,由於Objective-C本來就是動態類型,況且編譯器也會在編譯時做類型匹配,所以即便我們用NSArray<UIView*>也能在此數組中存放UIScrollView的對象,不會有編譯警告,更不會報錯。那么這個__kindof有啥用呢?
__kindof class_name 本意是將此類型指定為class_name或class_name的子類,告訴編譯器這兩者均能適配。現在對於編譯器類型檢查匹配倒是有一種情況存在,即結合C11標准中的泛型一起使用!由於C11中的generic selection表達式中的類型匹配完全由編譯器在編譯時進行匹配,而不會有任何運行時的動作(除非是動態變長類型,比如int[n]類型),所以這里可以由__kindof class_name 的形式來做一些更寬范圍的類型匹配。如以下代碼:
@interface MyObject : NSObject @end @implementation MyObject @end @implementation ViewController - (void)viewDidLoad { MyObject *obj = [[MyObject alloc] init]; int x = _Generic(obj, int:0, NSString*:1, NSObject*:2, default:-1); NSLog(@"x1 = %d", x); x = _Generic(obj, int:0, float:1, __kindof NSObject*:2, default:-1); NSLog(@"x2 = %d", x); [obj release]; } @end
正由於編譯器會在編譯時做檢查,所以這里第二個_Generic里就不能用NSString*,否則編譯器會認為NSString*與__kindof NSObject*兩者是相互兼容的類型,從而會產生匹配歧義。