Objective-C 范型

系統(tǒng)庫范型

Objective C支持輕量級(jí)的范型。在編寫自定義的范型類之前,我們先來看看Cocoa Touch的集合類(NSArray,NSDictionary,NSSet)對(duì)于范型的支持。

首先創(chuàng)建一個(gè)數(shù)組罕扎,這個(gè)數(shù)組只應(yīng)該用來存儲(chǔ)字符串:

NSMutableArray * array = [[NSMutableArray alloc] init];
[array addObject:@"1"];
//誤加了一個(gè)非字符串類型進(jìn)去
[array addObject:@(0)];

這時(shí)候,對(duì)數(shù)組中元素進(jìn)行遍歷,Crash:

for (NSString *string in array) {
    NSInteger length = [string length];
}

Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[__NSCFNumber length]: unrecognized selector sent to instance’

如果編譯器能幫助我們來確保加入數(shù)組中的元素都是String就好了

范型可以幫助我們解決這個(gè)問題:

//創(chuàng)建一個(gè)保存字符串的數(shù)組
NSMutableArray<NSString *> * array = [[NSMutableArray alloc] init];
[array addObject:@"1"];
[array addObject:@(0)];

同樣的昙篙,NSDictionary和NSSet也支持范型:

NSDictionary<NSString *, NSString *> *dictionary;
NSSet<NSString *> *set;

自定義范型類型

自定義一個(gè)范型類型很簡單,和其他語言類似诱咏,在聲明類的時(shí)候聲明占位符即可:

聲明一個(gè)Cup容器苔可,用來存儲(chǔ)一個(gè)值:

// Box.h
@interface Box<ObjectType> : NSObject

@property (nonatomic, readonly) ObjectType value;

- (void)seal:(ObjectType)value;

@end
// Box.m
@interface Box()

@property (strong, nonatomic) id value;

@end

@implementation Box

- (void)seal:(id)value{
    _value = value;
}

@end

接著,我們就可以這樣使用袋狞,

Box<NSString *> * box = [[Box<NSString *> alloc] init];
[box seal:@"1234"];
[box seal:@(1)]; // Warning

關(guān)于Objective C范型的幾點(diǎn)說明:

  • 在頭文件的類聲明中添加占位符ObjectType
  • 在.m文件中無法使用范型占位符焚辅,用id類型替代即可

約束

Objective 可以為范型增加輕量級(jí)的約束,比如要求ObjectType實(shí)現(xiàn)NSCopying協(xié)議:

@interface Box<ObjectType:id<NSCopying>> : NSObject

那么苟鸯,只有實(shí)現(xiàn)NSCopying的類型才能夠通過編譯:

//Error
Box<NSObject *> * box1 = [[Box<NSObject *> alloc] init];
//Work
Box<NSString *> * box2 = [[Box<NSString *> alloc] init];

逆變與協(xié)變

創(chuàng)建一個(gè)ViewBox和LabelBox法焰,并且把LabelBox賦值給ViewBox

Box<UIView *> * viewBox = [[Box alloc] init];
Box<UILabel *> * labelBox = [[Box alloc] init];
viewBox = labelBox; // Warning

這看似合理,又不合理倔毙。

  • 合理是因?yàn)閮蓚€(gè)Box中容納的類型不一樣埃仪,賦值的時(shí)候類型檢查不通過。
  • 不合理是因?yàn)楦鶕?jù)里氏替換原則陕赃,一個(gè)容納UILabel的Box卵蛉,那么也應(yīng)該是一個(gè)容納UIView的Box颁股。

協(xié)變

協(xié)變由關(guān)鍵字__covariant聲明。一個(gè)協(xié)變類型的范型占位符傻丝,如果變量A的占位符類型是子類甘有,那么可以把它賦值給占位符類型是父類的B。

也就是說葡缰,通過協(xié)變亏掀,我們能夠解決:一個(gè)容納UILabel的Box,那么也應(yīng)該是一個(gè)容納UIView的Box泛释。

// Box.h
@interface Box<__covariant ObjectType> : NSObject

@property (nonatomic, readonly) ObjectType value;

- (void)seal:(ObjectType)value;

@end

協(xié)變常常用于容器類型滤愕,像系統(tǒng)的NSArray,NSDictionary怜校,NSSet都采用了協(xié)變:

逆變

逆變(__contravariant),一個(gè)逆變類型的范型占位符间影,如果變量A的占位符類型是父類,那么可以把它賦值給占位符類型是子類的B茄茁。

逆變更側(cè)重類型的行為.

舉個(gè)例子:

//用來解析字符串中的數(shù)字
@interface StringPaser<__contravariant ObjectType:NSString *> : NSObject

- (NSString *)paseNumber;

@end

那么以下代碼則不會(huì)有編譯器警告

StringPaser<NSString *> * stringPaser = [[StringPaser alloc] init];
StringPaser<NSMutableString *> * mutableStringPaser = [[StringPaser alloc] init];
//父類賦值給子類
mutableStringPaser = stringPaser;

逆變要求父類和子類能夠提供同樣的行為魂贬,所以通過父類的接口創(chuàng)建的范型類,可以用來處理子類裙顽。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末付燥,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子愈犹,更是在濱河造成了極大的恐慌键科,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甘萧,死亡現(xiàn)場離奇詭異萝嘁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)扬卷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門牙言,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人怪得,你說我怎么就攤上這事咱枉。” “怎么了徒恋?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵蚕断,是天一觀的道長。 經(jīng)常有香客問我入挣,道長亿乳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮葛假,結(jié)果婚禮上障陶,老公的妹妹穿的比我還像新娘。我一直安慰自己聊训,他們只是感情好抱究,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著带斑,像睡著了一般鼓寺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勋磕,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天妈候,我揣著相機(jī)與錄音,去河邊找鬼朋凉。 笑死州丹,一個(gè)胖子當(dāng)著我的面吹牛醋安,可吹牛的內(nèi)容都是我干的杂彭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吓揪,長吁一口氣:“原來是場噩夢啊……” “哼亲怠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起柠辞,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤团秽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后叭首,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體习勤,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年焙格,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了图毕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡眷唉,死狀恐怖予颤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情冬阳,我是刑警寧澤蛤虐,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站肝陪,受9級(jí)特大地震影響驳庭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜氯窍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一饲常、第九天 我趴在偏房一處隱蔽的房頂上張望捏检。 院中可真熱鬧,春花似錦不皆、人聲如沸贯城。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽能犯。三九已至,卻和暖如春犬耻,著一層夾襖步出監(jiān)牢的瞬間踩晶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工枕磁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留渡蜻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓计济,卻偏偏與公主長得像茸苇,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子沦寂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354