泛型将接口的概念进一步延伸,“泛型”的字面意思就是广泛的类型。类、接口和方法代码可以应用于非常广泛的类型,代码与它们能够操作的数据类型不再绑定在一起,同一套代码可以用于多种数据类型,这样不仅可以复用代码,降低耦合性,而且还提高了代码的可读性以及安全性。
__covariant:协变, 子类转父类
__contravariant:逆变,父类转子类
//声明泛型
@interface Person<__covariant ObjectType> : NSObject
// 语言
@property (nonatomic, strong) ObjectType language;
Person *p = [[Person alloc] init];
p.language = chinese;
注:不遵守泛型仅仅是报警告
泛型使用场景:用于限制集合类型或某些属性到创建的时候才能确定,如Foundation框架中的NSArray就使用了泛型:
@property (nonatomic, strong)NSMutableArray *arr; //限制数据里面的集合是NSString类型
这样会在开发的过程中提供便利:1、从数组中取出来,可以使用点语法 2、给数组添加元素,有提示,同时可以避免添加错误类型。
注:在数组中,一般用可变数组添加方法,泛型才会生效;如果使用不可变数组添加元素,泛型没有效果(id类型不能使用点语法)。
自定义一个Person类,并且定义说的语言属性(Chinese,English);再声明Person,场景是不确定这个人会什么,在使用Person才知道这个Person会说什么语言。
自定义Person类,里面有一个language属性,不知道是什么类型的,自定义为泛型,并且添加协变和逆变:
//Person.h
#import
//声明泛型
//__covariant 协变,子类转父类 泛型名字是ObjectType
@interface Person<__covariant ObjectType> :NSObject
//语言
@property (nonatomic, strong) ObjectType language;
@end
定义一些语言类:
//Language
#import
@interface Language : NSObject
@end
//Chinese
#import "Language.h"
@interface Chinese : Language
@end
//English
#import "Language.h"
@interface English : Language
@end
1、首先是没有协变和逆变
#import
//泛型名字是ObjectType
@interface Person : NSObject
//语言
@property (nonatomic, strong) ObjectType language;
@end
- (void)test
{
Chinese *chinese = [[Chinese alloc] init];
English *english = [[English alloc] init];
// Chinese指定这个人会说的是chinese
Person *p = [[Person alloc] init];
p.language = chinese;
// English指定这个人会说的是english
Person *p1 = [[Person alloc] init];
p1.language = english;
}
2、添加了协变
#import
//第一步 声明泛型
//__covariant 子类转父类 泛型名字是ObjectType
@interface Person<__covariant ObjectType> : NSObject
// 语言
@property (nonatomic, strong) ObjectType language;
@end
// 子类转父类
- (void)covariant
{
Chinese *chinese = [[Chinese alloc] init];
Language *language = [[Language alloc] init];
// Chinese 只会说chinese
Person *p = [[Person alloc] init];
p.language = chinese;
// Language 都会说
Person *p1 = [[Person alloc] init];
p1 = p;//如果没添加协变会报指针类型错误警告
}
3、添加了逆变
#import
//第一步 声明泛型
//__contravariant 可以逆变,父类转子类 泛型名字是ObjectType
@interface Person<__contravariant ObjectType> : NSObject
//语言
@property (nonatomic, strong) ObjectType language;
@end
- (void)contravariant {
//第二步 定义泛型
Chinese *chinese = [[Chinese alloc] init];
Language *language = [[Language alloc] init];
// 父类转子类都会
Person *p = [[Person alloc] init];
p.language = language;
// Chinese只会说iOS
Person *p1 = [[Person alloc]init];
p1 = p; //如果没添加逆变会报指针类型错误警告
}
泛型是编程语言设计的很好的特性,可以有助于提高代码的规范程度与易读性,所以还是建议开发者们可以在编程中适当的时候多用泛型来实现。