Swift(二十三、泛型)

前端之家收集整理的这篇文章主要介绍了Swift(二十三、泛型)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

1、Swift入门学习笔记(第一版),对Swift的基础知识点进行梳理总结。知识点一直在变,只是作为参考,以苹果官方文档为准~

2、在学习完基本的知识点以后会结合官方文档及相关资料,在此版本的基础上进行添加更改。


二十三、泛型


根据需求定义、适用任何类型的、灵活且可重用的函数和类型。避免重复代码

泛型代码贯穿整个Swift,例如数组,字典类型都是泛型集,因为你可创建IntString各种不同类型的数组


1、泛型函数

1.1、交换两个值实例

例如交换两个Int值的常规写法

func swapTwoInts(inout a:Int,inout _ b:Int) {
    let temporary = a
    a = b
    b = temporary
}
var oneInt = 2
var theOtherInt = 18
print("BeforeSwap -> oneInt:\(oneInt),theOtherInt:\(theOtherInt)")
swapTwoInts(&oneInt,&theOtherInt)
print("AfterSwap -> oneInt:\(oneInt),theOtherInt:\(theOtherInt)")

Output:

BeforeSwap -> oneInt:2,theOtherInt:18
AfterSwap  -> oneInt:18,theOtherInt:2

但是有时候我们要交换两个Double值,两个String,就要写更多的函数,但是实际上实现功能相同,只是类型不同

因此可以利用泛型函数,可灵活的应用于任何类型

func swapTwoValues<T>(inout a:T,inout _ b:T) {
    let temporary = a
    a = b
    b = temporary
}
var oneString = "oneString"
var theOtherString = "theOtherString"
print("BeforeSwap -> oneString:\(oneString),theOtherString:\(theOtherString)")
swapTwoValues(&oneString,&theOtherString)
print("AfterSwap -> oneString:\(oneString),theOtherString:\(theOtherString)")

Output:

BeforeSwap -> oneString:oneString,theOtherString:theOtherString
AfterSwap  -> oneString:theOtherString,theOtherString:oneString

1.2、语法说明

func swapTwoValues<T>(inout a:T,inout _ b:T)

使用了占位类型名字(通常用字母T表示)来代替实际类型名,a,b必须是同一类型T

占位类型要用尖括号括起来<T>,告诉Swift其中的T函数所定义的一个类型,这样编译器就不会去查找命名为T的实际类型了

占位类型名字可以是任何有效的标识符

注意:swap函数swift标准库本来就有自带功能与上面的函数相同

swap(&oneString,&theOtherString) print("SwapAgain -> oneString:\(oneString),theOtherString:\(theOtherString)")

Output:

SwapAgain  -> oneString:oneString,theOtherString:theOtherString

2、泛型类型

创建一个泛型集类型:栈-pop-push

struct Stack<T> {
    var items = [T]()

    mutating func push(item:T) {
        items.append(item)
    }

    mutating func pop() -> T {
        return items.removeLast()
    }
}

注意:定义的时候要制定所属类型

var stackOfStrings = Stack<String>()
stackOfStrings.push("A")
stackOfStrings.push("B")
stackOfStrings.push("C")
stackOfStrings.push("D")
print(stackOfStrings.items)

let fromTheTop = stackOfStrings.pop()
print(fromTheTop)

Output:

["A","B","C","D"]
D

3、扩展一个泛型类型

泛型的扩展中可以使用原始类型的参数

扩展Stack添加一个只读计算属性,返回栈顶元素

extension Stack {
    var topItem:T? {
        return items.isEmpty ? nil : items[items.count-1]
    }
}
let topItem = stackOfStrings.topItem
print(topItem!)

Output:

C

4、类型约束

有时候使用泛型类型或者泛型函数上的类型需要强制约定为某种特定类型,譬如必须继承自某指定类的类型参数,或遵循一个特定的协议或协议构成

例如Swift中字典类型,其键类型必须可哈希确保它是唯一的,遵循Hashable协议。实际上所有的Swift基本类型(StringIntDoubleBool)都是默认可哈希的


4.1、类型约束语法

func someFunction<T: SomeClass,U: SomeProtocol>(someT: T,someU: U) {
    // 这里是函数主体
}
Equatable协议

官方文档提到了一个Swift的标准库协议,Equatable协议,遵循此协议,可以利用等式符(==)和不等符(!=)对任何两个该类型进行比较。因为通常并不是所有类型都能用==!=来进行比较,遵循此协议然后进行比较


5、关联类型

定义协议时,声明一个或多个关联类型作为协议定义的一部分。
给定类型的一个占位名,不用指定其实际类型,指定为typealias关键字

简单地说就是:类型的一个占位符,等到具体实现协议的时候才知道它具体是什么类型

定义一个容器协议,包含一个ItemType关联类型

protocol Container {
    typealias ItemType
    mutating func append(item:ItemType)
    var count:Int{ get }
}
//遵循Container协议的泛型Stack类型
struct Stack<T>:Container {
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    }
    mutating func pop() -> T {
        return items.removeLast()
    }

    //Swift会自动推断出被用作关联类型ItemType类型是T,不用显式地写出.
    //但是你写出来也没事 typealias ItemType = T
    mutating func append(item: T) {
        self.push(item)
    }

    var count:Int {
        return items.count
    }
}

var stackOfStrings = Stack<String>()
stackOfStrings.push("A")
stackOfStrings.push("B")
stackOfStrings.push("C")
stackOfStrings.push("D")
print(stackOfStrings.items)

let fromTheTop = stackOfStrings.pop()
print(fromTheTop,stackOfStrings.count)

Output:

["A","D"]
D 3

6、扩展一个存在的类型为一指定关联类型

之前又讲到,一个类都实现了协议的内容,但是还没遵循,可以通过空扩展来实现遵循

这里也一样,比如Swift自带的类Array都实现了Container的要求,因此可以扩展Array去遵循Container下而已,简单声明即可

extension Array:Container { }

定义此扩展后,可以将任何Array当做Container使用


7、Where语句

补充定义参数的约束。例如让一个关联类型遵循某个特定的协议,或特定的类型参数与关联类型相同

也可以写一个针对一个或多个关联参数的约束,以及一个或多个类型和关联类型间的等价关系

func allItemsMath<C1:Container,C2:Container where C1.ItemType == C2.ItemType,C1.ItemType:Equatable>(someContainer:C1,anotherContainer:C2) {
    //函数内容
}

上述约束描述:
C1C2遵循Container协议
C1ItemType遵循Equatable协议
C1ItemType类型与C2ItemType相同


OC不支持泛型

原文链接:https://www.f2er.com/swift/325416.html

猜你在找的Swift相关文章