Swift学习之泛型
2020-01-14 本文已影响0人
coderhlt
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
swapTwoInts(::) 函数很实用,但是它只能用于 Int 值。如果你想交换两个 String 值,或者两个 Double 值,你只能再写更多的函数。
一、泛型函数
为了解决类似上面的问题,我们可以用一个泛型函数去表示一个函数
func swapTwo<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwo(&someInt, &anotherInt)
var someString = “3”
var anotherString = “17”
swap(&someString, &anotherString)
- 占位符类型 T 就是一个类型形式参数指定并且命名一个占位符类型,紧挨着写在函数名后面的一对尖括号里(比如 <T> )。
- 大多数情况下,类型形式参数的名字要有描述性,比如 Dictionary<Key, Value> 中的 Key 和 Value ,借此告知读者类型形式参数和泛型类型、泛型用到的函数之间的关系。但是,他们之间的关系没有意义时,一般按惯例用单个字母命名,比如 T 、 U 、 V ,比如上面的 swapTwoValues(::) 函数中的 T 。
二、泛型类型
除了泛型函数,Swift允许你定义自己的泛型类型。它们是可以用于任意类型的自定义类、结构体、枚举,和 Array 、 Dictionary 方式类似。
class Stack<Element>{
var items = [Element]()
func push(_ item: Element) {
items.append(item)
}
func pop() -> Element {
return items.removeLast()
}
}
class Stack<Element>{
var items = [Element]()
func push(_ item: Element) {
items.append(item)
}
func pop() -> Element {
return items.removeLast()
}
}
var stack = Stack<String>()
stack.push(“ssss”)
var stack1 = Stack<Int>()
stack1.push(10)
- 这个泛型的 Stack 和非泛型版本的本质上是一样的,只是用一个叫做 Element 的类型形式参数代替了实际的 Int 类型。这个类型形式参数写在一对尖括号( <Element> )里,紧跟在结构体名字后面。Element 为稍后提供的”某类型 Element “定义了一个占位符名称。这个未来的类型可以在结构体定义内部任何位置以” Element “引用。在这个例子中,有三个地方将 Element 作为一个占位符使用:
struct Stack<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}
stackOfStrings = Stack<String>()
stackOfStrings.push(“uno”)
stackOfStrings.push(“dos”)
stackOfStrings.push(“tres”)
stackOfStrings.push(“cuatro”)
三、关联类型
在泛型函数中,你可以在函数名后面紧跟着一个类型形式参数,来表明泛型。然在协议中你不能这样去表示,编译器是不允许的。你需要在内部声明一个关联类型来表示泛型。
protocol Test {
associatedtype Element
mutating func append(_ item: Element)
var count: Int { get }
subscript(i: Int) -> Element { get }
}
- 用associatedtype关键字可以声明一个关联类型
- 关联类型作用:在协议中声明一个泛型类
class Student: Test {
typealias Element = String// 给关联类型设定真实类型
func append(_ item: String) {}
var count: Int = 0
subscript(i: Int) -> String {
return “333”
}
}
class Person: Test {
typealias Element = Int// 给关联类型设定真实类型
func append(_ item: Int) {}
var count: Int = 0
subscript(i: Int) -> Int {
return 333
}
}
四、不透明类型
如果协议中有 associatedtype,
截屏2020-01-14下午5.12.29.png
解决方案1:使用泛型
func test<T:Runnable>(a:Int) -> T{
return Person() as! T
}
解决方案2:不透明类型
使用some关键字声明一个不透明类型
func test(a:Int) -> some Runnable{
return Person()
}