Objective-C 泛型 協(xié)變 逆變

為什么要使用泛型

在使用NSArray, NSSet, NSDictionary 中都有使用泛型.

先來看一段沒有使用泛型的的代碼

NSMutableArray *arr = [NSMutableArray array];

[arr addObject:@1];

[arr addObject:@"wang"];

[arr addObject:@{}];

在這段代碼中可以給數(shù)組中添加任意對象, 但是實際情況中我們希望使用數(shù)組用來保存同一種類型的變量.

實際情況中,我們可能希望使用數(shù)組保存一組NSString,但是我們操作失誤在數(shù)組中添加的一個NSNumber使用上面的代碼,在編譯階段,Xcode并不會提示錯誤或給出警告,但是在實際使用中,我們認(rèn)為這個數(shù)組中都是NSString類型的變量,導(dǎo)致對NSNumber使用NSString的方法導(dǎo)致程序crash,顯然這樣的程序是不健壯的.

還好使用泛型可以解決這樣的問題,代碼如下

image.png

使用泛型指定數(shù)組中的類型為NSString,當(dāng)我們在數(shù)組中添加其他類型時,就會出現(xiàn)提示.

image.png
image.png

在我們沒有指定泛型時,提示顯示可以添加id類型

當(dāng)我指定泛型時,提示的是在聲明過程中與泛型對應(yīng)的類型.

使用集合時用泛型聲明可以幫助你檢查集合中的類型,還能提示集合中應(yīng)存放的類型.


如何使用泛型

我們先看一下NSArray中泛型的使用

image.png
image.png

通過觀察發(fā)現(xiàn),泛型起到的作用就是占位符的作用.

聲明一個數(shù)組的指定泛型為NSString *, ObjectType就是一個占位符, 在接口中任何使用ObjectType泛型占位符的時候都會替換為NSString *類型.

了解了系統(tǒng)泛型使用方法然后自己創(chuàng)建一個ClassStack使用泛型.

@interface Stack <__covariant T> : NSObject

- (void)push:(T)obj;

- (T)pop;

@end

在聲明.h 我們都可以使用泛型T作為占位符.

image.png

在類擴(kuò)展和分類中并不能使用T泛型.

如果要做分類和類擴(kuò)展中使用泛型需要重新指定.

image.png

在實現(xiàn)中是不能使用泛型的.


限制泛型

通常我們在使用泛型時可以代替任意id類型,但有時我們使用泛型時,希望對泛型進(jìn)行限制,我們希望泛型為UIView類簇中的類型.

image.png

很顯然這并不是我們希望看到了,所以我們可以對泛型進(jìn)行限制

@interface Stack <__covariant T : UIView *> : NSObject

- (void)push:(T)obj;

- (T)pop;

@end
image.png

使用上面聲明方法可以解決問題.

同時也可以限制泛型遵守指定的協(xié)議

@interface Stack <__covariant T : id<protocol>> : NSObject

- (void)push:(T)obj;

- (T)pop;

@end

協(xié)變 逆變

在上面我們開到了關(guān)鍵字__covariant,下面就來看看這個關(guān)鍵字的作用

__covariant:協(xié)變, 子類轉(zhuǎn)父類 :也就是將子類的指針賦值給父類(多態(tài)的延伸)

__contravariant:逆變 父類轉(zhuǎn)子類:也就是將父類的指針賦值給子類(暫時沒有想到有什么作用,如果有哪位大佬知道歡迎指點一二).

在這里我們創(chuàng)建兩個類Animal和他的子類Dog.

//測試代碼
Stack <Dog *> *stack1 = [Stack new];
Stack <Animal *> *stack2 = [Stack new];
stack1 = stack2;
stack2 = stack1;

接下來我們分別來看看協(xié)變和逆變的特性.

// 逆變 父類指向子類
@interface Stack <__contravariant T : Animal *> : NSObject
image.png
// 協(xié)變 子類指向父類
@interface Stack <__covariant T : Animal *> : NSObject
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • object 變量可指向任何類的實例,這讓你能夠創(chuàng)建可對任何數(shù)據(jù)類型進(jìn)程處理的類。然而,這種方法存在幾個嚴(yán)重的問題...
    CarlDonitz閱讀 1,020評論 0 5
  • 前言 泛型(Generics)的型變是Java中比較難以理解和使用的部分,“神秘”的通配符,讓我看了幾遍《Java...
    珞澤珈群閱讀 8,127評論 12 51
  • 泛型是Java 1.5引入的新特性。泛型的本質(zhì)是參數(shù)化類型,這種參數(shù)類型可以用在類、變量、接口和方法的創(chuàng)建中,分別...
    何時不晚閱讀 3,117評論 0 2
  • 死磕自己,服務(wù)大眾! 今天是天下的母親節(jié)!祝天下的母親節(jié)日快樂!本想回番禺和母親過節(jié),但在深圳兒子的母親,兒子母親...
    張錦全閱讀 362評論 0 0
  • 有很多人都曾問過我,娛樂圈的人這么多,為什么偏偏只喜歡楊冪,我總是笑了笑,沒有回答。因為我覺得欣賞一個人,或是因為...
    小傻lapin閱讀 443評論 0 0

友情鏈接更多精彩內(nèi)容