二轉:https://blog.csdn.net/imkata/article/details/78859482
一、泛型作用
? ? 泛型:限制類型
? ? 為什么要推出泛型?迎合swift
? ? 泛型作用:
????????1、限制類型;
? ? ? ? 2、提高代碼規劃,減少溝通成本,一看就知道集合中是什么東西或者類隸屬于什么父類型。
二、泛型用法:
? ? __covariant:協變,子類轉父類;
????eg:
@interface MyPageViewController<__covariant ViewControllerType:UIViewController *> : MyBaseViewController
@interface MyKeyValues <__covariant KeyType,__covariant ObjectType> : NSObject
? ? __contravariant:逆變,父類轉子類;
※個人理解:類似于基礎數據類型大轉?。╛_contravariant),小轉大(__covariant)。
1、泛型聲明:在聲明類的時候,在類的后面<泛型名稱>
// 第一步 聲明泛型
@interface Person<__covariant ObjectType> : NSObject
// 語言
@property (nonatomic, strong) ObjectType language;
2、使用泛型 類型<限制類型>
// iOS
Person<iOS *> *p = [[Person alloc] init];
p.language = ios;
※不遵守泛型僅僅是報警告
三、泛型在開發中的使用
? ? 泛型在開發中使用場景:
????1、用于限制集合類型
? ? 泛型好處:
????1、從數組中取出來,可以使用點語法關聯;
????2、給數組添加元素,有提示。
????@property (nonatomic, strong) NSMutableArray<NSString *> *arr;
????限制數據里面的集合是NSString類型。
? ? ※ id是不能使用點語法
? ? 泛型注意點:
????在數組中,一般用可變數組添加方法,泛型才會生效;
????如果使用的不可變數組,添加元素,泛型沒有效果。
四、泛型使用舉例
? ? 什么時候使用泛型?
????在聲明類的時候,不確定某些屬性或者方法類型,在使用這個類的時候才確定,就可以采用泛型。
? ? 舉例場景:自定義Person,會一些編程語言(iOS, Java),在聲明Person,不確定這個人會什么,在使用Person才知道這個Person會什么語言。
? ? 如果沒有定義泛型,默認就是id類型。
(一)、先自定義類
1、自定義Person類。
里面有一個language屬性,不知道是什么類型的,自定義為泛型,并且添加協變和逆變聲明。
// Person.h
#import <Foundation/Foundation.h>
// 第一步 聲明泛型
// __covariant 協變,子類轉父類? 泛型名字是ObjectType
@interface Person<__covariant ObjectType> :NSObject
// 語言
@property (nonatomic, strong) ObjectType language;
@end
2、定義語言類Language
#import <Foundation/Foundation.h>
@interface Language : NSObject
@end
3、定義語言子類Java語言
#import "Language.h"
@interface Java : Language
@end
4、定義語言子類iOS語言
#import "Language.h"
@interface iOS : Language
@end
(二)、下面介紹如何使用
1、首先是沒有協變和逆變
#import <Foundation/Foundation.h>
// 泛型名字是ObjectType
@interface Person<ObjectType> : NSObject
// 語言
@property (nonatomic, strong) ObjectType language;
@end
- (void)test
{
? ? Java *java = [[Java alloc] init];
? ? iOS *ios = [[iOS alloc] init];
? ? // iOS? 指定這個人會的是iOS
? ? Person<iOS *> *p = [[Personalloc] init];
? ? p.language = ios;
? ? // Java? 指定這個人會的是Java
? ? Person<Java *> *p1 = [[Personalloc] init];
? ? p1.language = java;
}
2、添加了協變
#import <Foundation/Foundation.h>
// 第一步 聲明泛型
// __covariant 子類轉父類? 泛型名字是ObjectType
@interface Person<__covariant ObjectType> : NSObject
// 語言
@property (nonatomic, strong) ObjectType language;
@end
// 子類轉父類
- (void)covariant
{
? ? iOS *ios = [[iOS alloc] init];
? ? Language *language = [[Language alloc] init];
? ? // 只會iOS
? ? Person<iOS *> *p = [[Person alloc] init];
? ? p.language = ios;
? ? // Language 都會
? ? Person<Language *> *p1 = [[Person alloc] init];
? ? p1 = p;
????// ※如果沒添加協變會報指針類型錯誤警告
}
3.添加了逆變
#import <Foundation/Foundation.h>
//第一步 聲明泛型
//__contravariant 可以逆變,父類轉子類? 泛型名字是ObjectType
@interface Person<__contravariant ObjectType> : NSObject
// 語言
@property (nonatomic, strong) ObjectType language;
@end
- (void)contravariant {
? ? //第二步 定義泛型
? ? iOS *ios = [[iOS alloc] init];
? ? Language *language = [[Language alloc] init];
? ? // 父類轉子類? 都會
? ? Person<Language *> *p = [[Person alloc] init];
? ? p.language = language;
? ? // 只會iOS
? ? Person<iOS *> *p1 = [[Person alloc] init];
? ? p1 = p;?
????// ※如果沒添加逆變會報指針類型錯誤警告
}