Objective-C輕量級泛型


在Apple發布Xcode7的時候,不僅把Swift編程語言升級到了2.0版本,而且還對Objective-C做了許多提升,包括引入__nonnull/__nullable。其中,對於Objective-C編程語言本身而言,更為有用的便是輕量級泛型。

其中,比較明顯的體現就是NSArray、NSDictionary這些容器類都采用了新引入的輕量級泛型。通過輕量級泛型,我們可以非常容易地獲取其中的元素,並訪問其相印特有的屬性和方法。我們舉一個簡單例子來闡明輕量級線程帶來的方便:

    // 不帶泛型的情況
    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”。

與C11的generic selection所不同的是,Objective-C自帶的泛型其本質為covariant type,即協變類型。也就是,其泛型與Java的有些類似。它要求泛型必須是一個Objective-C類類型,即至少為id類型。對於上述NSArray的例子,我們在聲明一個Objective-C對象引用時,通過在類名后面添加<NSNumber*>來指明當前NSArray里的元素都是NSNumber*類或其子類類型。這樣,我們在訪問其元素時可直接訪問其intValue方法。

下面我們介紹如何自己定義一個泛型類。其語法描述如下:

@interface    class_name    <    __covariant    type_identifier    >    inherit_expression

這里,class_name就是類名;type_identifier是類型標識符,該標識符可以由程序員自己命名;最后的inherit_expression表示繼承某個父類以及/或實現某些協議。

這里引入了一個新的關鍵字——__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方法以獲得其字符串長度。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM