iOS强大的泛型
在学习安卓的过程中,发现java
的泛型机制特别的好用,Objective-C
是一门动态性弱类型语言,例如毫无关系的两个类A
和B
,A *a = [[B alloc] init]
在Objective-C
编译和运行中都不会出错。但是A a = new B()
在java
中编译失败。这样,可以强制编程人员注意类型转换。
在不了解Objective-C
的泛型之前,我一直以为Objective-C
的泛型是鸡肋,例如:
|
我声明一个NSString
类型的泛型数组,但是我往数组中添加的是一个NSObject
类型的对象,虽然编译器会警告,但并不会报错(大部分程序猿也会忽略这个警告)。所以,我认为Objective-C
的泛型是鸡肋。当然,这只是我之前的自以为(还是自己学的不深入)。但是今天看过一篇介绍Objective-C
的泛型以后,才发现Objective-C
也能做到编译时报错。
这篇文章就来说说泛型
- 泛型是什么
- 为什么要用泛型
- 泛型怎么用
- 泛型进阶
- 泛型的延伸使用
泛型是什么
泛型可以让你使用定义的类型来编写灵活的、可重用的函数和类型,可以避免重复,以清晰,抽象的方式表达其意图。用人话来说,泛型给予我们更抽象的封装函数或类的能力,不严谨的来讲,一门语言越抽象使用越方便。Objective-C
中的NSArray
和NSDictionary
都是基于泛型编写的集合类型,如果不太理解也没关系,下面讲几个例子理解下。
1. Objective-C中的泛型
在2015年WWDC
上苹果推出了Swift2.0
版本,为了让开发者从Objective-C
更好得过度到Swift
上,苹果也为Objective-C
带来了Generics
泛型支持
所以,我们经常看到的OC
中的泛型比如:
|
或者:
|
我们先看看OC
中的泛型大概做了些什么:
打开NSArray.h
可以看到:
|
我们会发现,无论是查找还是初始化,都使用了ObjectType
。
声明一个Generics
的格式如下:
|
占位类型后也可以加入类型限制,比如:
|
若不加入类型限制,则表示接受id即任意类型。我们先来看看一个简单使用泛型的例子:
|
其中T为我们提现声明好的占位类型名称,可自定义(如ObjectType等等),需要注意的是该T的作用域只限于@interface MyCollection
到@end
之间,.m
文件则不能使用。至于泛型占位名称之前的修饰符则可分为两种:__covariant(协变)
和__contravariant(逆变)
两者的区别如下:
__covariant
意味协变,意思是指子类可以强制转换为父类,遵从的是SOLID
中的L
即里氏替换原则,大概可以描述为:程序中的对象应该是可以在不改变程序正确性的前提下被它的子类所替换的。
__contravariant
意为逆变,意思是指父类可以强制转换为子类。
用我们上面自定义的泛型来解释:
|
默认不指定泛型类型的情况下,不同类型的泛型可以相互转换。
这个时候就可以在占位泛型名称之前加入修饰符__covariant
或__contravariant
来控制转换关系,像NSArray
就使用了__covariant
修饰符。
引申:
在上面的这个例子中,声明属性时,还可以在泛型钱添加__kindof
关键词,表示其中的类型为该类型或者其子类,如:
|
之后就可以这样调用了
|
也就不会有警告了。