博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS泛型
阅读量:6712 次
发布时间:2019-06-25

本文共 3703 字,大约阅读时间需要 12 分钟。

hot3.png

  

  这一篇文章主要来介绍泛型的意义、使用与声明方法等。

1.泛型:限制类型

  1.1.泛型使用场景:

    1.在集合(数组NSArray、字典NSDictionary、集合NSSet)中使用泛型比较常见。

    2.当声明一个类,但是类里面的某些属性的类型不确定的时候,我们才使用泛型。

  1.2.泛型书写规范

    在类型后面定义泛型:NSMutableArray<UITouch *> dataArray

  1.3.泛型修饰

    只能修饰方法的调用。

  1.4.泛型好处:

    1.提高开发的规范,减少程序员之间的交流。

    2.通过集合取出来的对象,可以直接当做泛型对象使用。这样我们就可以直接使用.点语法。

  

2.代码使用泛型:

  2.1.声明一个泛型为NSString的数组

1 // 具体做法就是在 NSMutableArray 后带一个 
,尖括号内部即为泛型类型2 @property (nonatomic, strong, nullable) NSMutableArray
*dataArray;

  2.2.当我们要给数组添加对象或取出对象的时候,系统就会自动提示应该传入或者取出来的对象的类型,这个类型就是你刚才声明的泛型类型

复制代码

1     // 1.没有使用泛型 2 //    [self.dataArray addObject:<#(nonnull id)#>]; 3  4     // 2.使用泛型 5 //    [self.dataArray addObject:<#(nonnull NSString *)#>]; 6      7     // 3.添加不正确的类型,会出现警告 8 //    [self.dataArray addObject:@1]; 9     10     // 4.我们可以直接将集合中取出来的对象当做泛型使用11     NSInteger length = [self.dataArray.firstObject length];

复制代码

  

  基本上实现了使用泛型过程中可能出现的情况。

 

3.泛型的自定义

  刚才我们只是实现了系统类NSMutableArray的泛型。接下来我们要考虑下,我们怎么样在我们自己的类中声明一个泛型的属性呢?

  为了这个目的,我们创建一个 Language 的类表示 “语言”。并且创建两个 Language 的子类,分别叫 Java 和 IOS 。很明显这两个是“某一个类型的语言”。我们创建一个Person的类,给类声明一个泛型,在类的 .h 文件中声明一个声明一个属性,这个属性表示这个人会的语言,即为 IOS 或者 Java 。那么我们有以下两种声明方式:  

1 // 语言2 // 1.id:任何对象都能传进来3 //@property (nonatomic, strong, null_unspecified) id language;4 // 2.Language:在外面调用的时候不能提示具体是哪种语言5 //@property (nonatomic, strong, null_unspecified) Language *language;

  因为 Language 这个语言并不能代表这个 Person 究竟会什么语言,我们需要的属性时 IOS 和 Java。这两种都可以在调用的时候传入 Java 和 IOS 两种对象,但它们的缺点也非常明显,若使用 id 则我们可以传入任何对象,而不只是 Java 和 IOS ;使用 Language * 呢,我们没有办法在编译的时候确定这个人究竟会什么语言,而只能在运行时判断。有没有办法让我们在编译的时候就能知道 Person 具体会哪种 Language 呢?

  办法就是泛型。

  声明自定义类的泛型,我们需要做这样一步:

1 // (给类)声明一个泛型2 @interface JTPerson
: NSObject

  看出区别了吗?我们在 interface 类名之后加了一对尖括号 <> ,中间是 ObjectType 。这个就代表泛型。这样我们在声明属性的时候就可以这么写: 

1 @property (nonatomic, strong, null_unspecified) ObjectType language;

  也就是,我们现在不指定具体的类型,而在实例化这个类的时候确定这个泛型。若不确定,那么所有的 ObjectType 会自动变成 id 。像这样:

复制代码

1     // iOS 2     JTPerson
*iOSP = [[JTPerson alloc] init]; 3 4 // [iOSP setLanguage:@"123"]; 5 6 // [iOSP setLanguage:<#(IOS * _Null_unspecified)#>]; 7 8 // [iOSP setLanguage:[[Java alloc] init]]; 9 10 // Java11 JTPerson
*javaP = [[JTPerson alloc] init];12 13 // [javaP setLanguage:@"123"];14 15 // [javaP setLanguage:<#(Java * _Null_unspecified)#>];16 17 // [javaP setLanguage:[[IOS alloc] init]];

复制代码

  这样,我们在声明 Person这个类的时候,就顺便声明了这个类的泛型。这样系统就会在你使用到泛型的属性与方法的时候,自动提醒你声明的泛型类型了。

 

4.泛型的协变与逆变

  首先我们来看一个方法:

1 - (void)touchesBegan:(NSSet
*)touches withEvent:(UIEvent *)event {2 3 [touches anyObject];4 }

  大家应该很熟悉这个方法了。这就是 UIViewController 继承自 UIResponder 的方法,是点击这个视图控制器之后事件链的最后一环。这时候经过上面的学习,我们会看到这其中就使用了泛型: (NSSet<UITouch *> *) 。这样我们点进集合 NSSet 会发现它是这样写的:

  前后我们都很清楚: interface:声明;NSSet:集合;ObjectType:泛型;NSObject:是NSSet的父类,也是根类;后面尖括号中表示的是遵守的协议。

  那么 __covariant 代表什么?

  这里我们先来学习两个单词: covariant:协变的 contravariant:逆变的。

  那么 __covariant协变 代表什么?

 

  我们来试一下。在刚才的自定义类 Person 的泛型 ObjectType 前加这样一条修饰: __covariant

1 @interface JTPerson<__covariant ObjectType> : NSObject

  然后在调用的时候,我们声明两个实例,泛型分别为父类 Language 和子类 IOS。这样若泛型为 IOS 的 Person 想给泛型为 Language 的 Person 赋值,会怎么样:

复制代码

1     // 1.协变2     // iOS3     JTPerson
*iOSP = [[JTPerson alloc] init];4 5 // Language6 JTPerson
*p = [[JTPerson alloc] init];7 8 // 如果子类想给父类赋值,协变9 p = iOSP;

复制代码

  并没有报错。

  也就是说,若泛型为子类的对象想给泛型为父类的对象赋值的时候,我们需要在泛型前面添加 协变__convariant ,告诉编译器,这样转换没有问题。

  同理,__contravariant逆变就是若泛型为父类的对象想给泛型为子类的对象赋值的时候,我们需要在泛型前面添加 逆变__contravariant ,告诉编译器,这样转换没有问题。

  这就是协变与逆变的含义。

  协变与逆变本身是面向对象继承的语言的一个特性,也并不只应用在泛型这里。

转载于:https://my.oschina.net/HeroOneHY/blog/1154488

你可能感兴趣的文章
我的友情链接
查看>>
heap中的heapify与依次压入队列的差异
查看>>
找工作体会
查看>>
linux之使用man查看命令手册
查看>>
健康常识
查看>>
Centos 6.3安装配置supervisor进程管理工具
查看>>
jquery ajax超时设置
查看>>
有兴趣,便且坚持下来。。。。。make it
查看>>
我的友情链接
查看>>
takeown 卸载cygwin
查看>>
spring定时器----JobExecutionContext
查看>>
AIX账户安全管理
查看>>
ARM流水线
查看>>
5015/5/5 谈谈http协议
查看>>
nagios安装部署
查看>>
java中重载与重写的区别
查看>>
Fix:方便快捷的Web开发平台
查看>>
IT管理员如何保证你的内网安全?
查看>>
交互原型画得丑?29个优秀UI/UX线框草图
查看>>
用U盘安装debian系统
查看>>