Objective-C泛型介绍和用法 – Objective-C开发教程

上一章Objective-C开发教程请查看:Objective-C Foundation框架全解
泛型是比较有用的,泛型类似于万能指针id,以及void*。特别是在设计数据结构和算法的时候,如果你学过数据结构都知道,任意数据结构必定包含数据项,如果要提供以后复用,那就不好将这个数据项的数据类型写死了,使用泛型就可以将其定为任意类型,对于任意类型的数据都能使用该数据结构了。
OC中的NSArray和NSDictionary就是基于这个想法,容纳所有类型,可以使用NSObject、id指针、void*指针,而泛型除了能容纳指定的类型,还可以进行类型检查,在调用的时候指定数据类型,让代码更清晰。
泛型的定义和使用对某个类提供一个泛型声明,最简单的是使用以下语法:

@interface List< T> : NSObject @property(nonatomic, copy)T t; -(instancetype)initWith: (T)t; @end

注意这里的泛型T相当于id,它是一个指针,也是一个类型,在声明文件中涉及到T的都可以使用T类型声明,但是在实现文件中就不能再使用T了,要将对应的T类型变为id类型(实在有点麻烦),如下:
@implementation List -(instancetype)initWith: (id)t{ if(self = [super self]){ _t = t; } return self; } @end

下面是使用示例:
List< NSString> *list = nil; list = [[List alloc]initWith: @"Hola"];

【Objective-C泛型介绍和用法 – Objective-C开发教程】以上是一种简单的泛型定义,另外我们还可以限制泛型T继承指定的类,传入的类可以是父类或父类的子类,如下:
@interface List< T : NSObject*> : NSObject @end

注意继承父类使用的是指针。泛型中不能指定T遵循的协议,不过也没办法,OC中的协议和Java的接口不同。而且要注意添加泛型定义是在类名和父类之间添加< T>,若要实现某个协议,则在父类后面添加< Protocol>,例如:
@interface List< T : NSObject*> : NSObject < NSCopying> @end

再次体现了OC的语法繁杂——
协变和逆变:__covariant & __contravariant协变是使用__covariant关键字,什么意思呢?如果A是B的父类,将A类型传入一个泛型中,并进行赋值,如下:
List< B> *b = [[List alloc]initWith: @"AA"]; List< A> *a = b;

以上会产生警告,消除警告则可以使用__covariant关键字修饰泛型T,如下:
@interface List< __covariant T> : NSObject @end

__covariant修饰的T,表示当需要将子类转为父类的时候,如上面的b中的B类转为a中的A父类,也就允许将子类转为父类。
__contravariant则是相反的意思,将泛型中的父类转为子类。

    推荐阅读