swift中泛型的使用
2021-07-16 本文已影响0人
傲骨天成科技
一、函数中使用泛型
比如一个打印字符串的方法:
func myPrintString(str:String){
print(str)
}
打印出来就直接是字符串类型的
如果我们打印的是一个任意类型的呢?我们可以使用Any试试
// 打印任何东西
func myPrintAny(arg:Any){
print(any1)
}
使用Any是可以的,但是如果我们有多个参数呢,且要求一致呢?
func myPrintAny(any1:Any, any2:Any){
print(any1)
print(any2)
}
这样的写法是可以使用任意类型了,但是没有限制住两个参数类型是一样的。导致的结果是对调用此API的人要求特别高,不是我们想要的。
这时泛型就有了用武之地了
// 打印任何东西
func myPrint<T>(any1:T, any2:T){
print(any1)
print(any2)
}
从上面的几个事例中可以看出泛型的优势,提升了代码的可复用性、安全性。
泛型和Any的区别?
从表面上看两者没有区别。但是,泛型可以用于定义灵活的函数,类型检查仍然由编译器负责。而Any可以逃避开我们swift的类型系统。因此,可以的话尽量不要使用Any。
二、类中泛型
实现一个数组中的元素可以是任意类型,但是所有元素又必须是同一类型。
//类作用域
class YJKStack<T>: NSObject {
//栈空间
private var list:[T] = []
//进栈
public func push(item:T){
list.append(item)
}
//出栈
public func pop() -> T{
return list.removeLast()
}
}
当我们扩展含有泛型的类的时候,泛型是可以直接在扩展中使用的。
extension YJKStack{
/// 获取栈顶元素
public func getLast() -> T?{
return list.last
}
}
三、泛型类型约束
1.泛型是某个类的子类
class YJKProtocolStack<T: CClass >: NSObject {
//栈空间
private var list:[T] = []
//进栈
public func push(item:T){
list.append(item)
}
//出栈
public func pop() -> T{
return list.removeLast()
}
}
class CClass : NSObject {
}
2.泛型必须要实现某个或几个协议
//class YJKProtocolStack<T: A&B> 须实现多个协议的话,用 & 符号链接就好啦。
class YJKProtocolStack<T: A&B>: NSObject {
//栈空间
private var list:[T] = []
//进栈
public func push(item:T){
list.append(item)
}
//出栈
public func pop() -> T{
return list.removeLast()
}
}
protocol A {
func myPrintA(item: Int)
}
protocol B {
func myPrintB(item: Int)
}
class ClassAB: NSObject, A, B {
func myPrintA(item: Int) {
print("我的天神A")
}
func myPrintB(item: Int) {
print("我的天神B")
}
}
// 使用
var stack:YJKProtocolStack = YJKProtocolStack<ClassAB>.init()
四、结构体中的泛型使用
和类里面的泛型使用是一样的
五、协议中泛型使用需要使用关联类
//一敲出来,编译器就提示你错误啦,并且告诉你怎么写了。
protocol C<T> {
}
//正确的写法就是下面这样的哦
protocol C {
// Swift 中使用 associatedtype 关键字来设置关联类型实例
// 具体类型由实现类来决定
associatedtype ItemType
func itemAtIndex(index:Int) -> ItemType
func myPrint(item:ItemType)
// 局部作用域的泛型和类的写法是一样的。
func test<T>(a:T)
}
//协议的泛型约束
protocol D {
associatedtype ItemType:A
}
需要结合使用该协议的类是怎么使用的
//遵循了 C 协议的类
class CClassOne<T>:C{
//要指定 C 协议中, ItemType 的具体类型
typealias ItemType = T
public var list:[ItemType] = []
//协议方法的实现
func itemAtIndex(index:Int) -> ItemType{
return list[index]
}
func myPrint(item:ItemType){
}
func test<T>(a: T) {
}
}
//实现2
class CClassTwo:C{
typealias ItemType = Int
public var list:[ItemType] = []
func itemAtIndex(index:Int) -> ItemType{
return list[index]
}
func myPrint(item:ItemType){
}
func test<T>(a: T) {
}
}
通过上面的例子,看出只要实现类中指定ItemType的类型就好了。这个类型 还可以是个泛型,也可以是具体的数据类型。