Objective-C 泛型 协变 逆变

为什么要使用泛型

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

先来看一段没有使用泛型的的代码

NSMutableArray *arr = [NSMutableArray array];

[arr addObject:@1];

[arr addObject:@"wang"];

[arr addObject:@{}];

在这段代码中可以给数组中添加任意对象, 但是实际情况中我们希望使用数组用来保存同一种类型的变量.

实际情况中,我们可能希望使用数组保存一组NSString,但是我们操作失误在数组中添加的一个NSNumber使用上面的代码,在编译阶段,Xcode并不会提示错误或给出警告,但是在实际使用中,我们认为这个数组中都是NSString类型的变量,导致对NSNumber使用NSString的方法导致程序crash,显然这样的程序是不健壮的.

还好使用泛型可以解决这样的问题,代码如下

image.png

使用泛型指定数组中的类型为NSString,当我们在数组中添加其他类型时,就会出现提示.

image.png
image.png

在我们没有指定泛型时,提示显示可以添加id类型

当我指定泛型时,提示的是在声明过程中与泛型对应的类型.

使用集合时用泛型声明可以帮助你检查集合中的类型,还能提示集合中应存放的类型.


如何使用泛型

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

image.png
image.png

通过观察发现,泛型起到的作用就是占位符的作用.

声明一个数组的指定泛型为NSString *, ObjectType就是一个占位符, 在接口中任何使用ObjectType泛型占位符的时候都会替换为NSString *类型.

了解了系统泛型使用方法然后自己创建一个ClassStack使用泛型.

@interface Stack <__covariant T> : NSObject

- (void)push:(T)obj;

- (T)pop;

@end

在声明.h 我们都可以使用泛型T作为占位符.

image.png

在类扩展和分类中并不能使用T泛型.

如果要做分类和类扩展中使用泛型需要重新指定.

image.png

在实现中是不能使用泛型的.


限制泛型

通常我们在使用泛型时可以代替任意id类型,但有时我们使用泛型时,希望对泛型进行限制,我们希望泛型为UIView类簇中的类型.

image.png

很显然这并不是我们希望看到了,所以我们可以对泛型进行限制

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

- (void)push:(T)obj;

- (T)pop;

@end
image.png

使用上面声明方法可以解决问题.

同时也可以限制泛型遵守指定的协议

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

- (void)push:(T)obj;

- (T)pop;

@end

协变 逆变

在上面我们开到了关键字__covariant,下面就来看看这个关键字的作用

__covariant:协变, 子类转父类 :也就是将子类的指针赋值给父类(多态的延伸)

__contravariant:逆变 父类转子类:也就是将父类的指针赋值给子类(暂时没有想到有什么作用,如果有哪位大佬知道欢迎指点一二).

在这里我们创建两个类Animal和他的子类Dog.

//测试代码
Stack <Dog *> *stack1 = [Stack new];
Stack <Animal *> *stack2 = [Stack new];
stack1 = stack2;
stack2 = stack1;

接下来我们分别来看看协变和逆变的特性.

// 逆变 父类指向子类
@interface Stack <__contravariant T : Animal *> : NSObject
image.png
// 协变 子类指向父类
@interface Stack <__covariant T : Animal *> : NSObject
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,547评论 4 374
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,787评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,175评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,752评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,169评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,056评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,195评论 2 321
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,980评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,724评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,872评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,344评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,667评论 3 264
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,379评论 3 245
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,202评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,992评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,189评论 2 286
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,987评论 2 279

推荐阅读更多精彩内容

  • object 变量可指向任何类的实例,这让你能够创建可对任何数据类型进程处理的类。然而,这种方法存在几个严重的问题...
    CarlDonitz阅读 884评论 0 5
  • 前言 泛型(Generics)的型变是Java中比较难以理解和使用的部分,“神秘”的通配符,让我看了几遍《Java...
    珞泽珈群阅读 7,583评论 12 51
  • 泛型是Java 1.5引入的新特性。泛型的本质是参数化类型,这种参数类型可以用在类、变量、接口和方法的创建中,分别...
    何时不晚阅读 2,978评论 0 2
  • 死磕自己,服务大众! 今天是天下的母亲节!祝天下的母亲节日快乐!本想回番禺和母亲过节,但在深圳儿子的母亲,儿子母亲...
    张锦全阅读 286评论 0 0
  • 有很多人都曾问过我,娱乐圈的人这么多,为什么偏偏只喜欢杨幂,我总是笑了笑,没有回答。因为我觉得欣赏一个人,或是因为...
    小傻lapin阅读 379评论 0 0