免费开源的iOS开发学习平台

Swift:19 泛型

泛型让你能够根据自定义的需求,编写出适用于任意类型、灵活可重用的函数及类型。它能让你避免代码的重复,用一种清晰和抽象的方式来表达代码的意图。

泛型函数

泛型函数可以适用于任何类型,下面定义一个swapTwoValues(::) 函数可以用来交互任意两个同类型的变量的值。

func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var one = 1,two = 2
swapTwoValues(&one, &two)
print("One=\(one),Two=\(two)")
//打印:One=2,Two=1
var strOne = "One", strTwo = "Two"
swapTwoValues(&strOne, &strTwo)
print("One=\(strOne),Two=\(strTwo)")
//打印:One=Two,Two=One
var doubleOne = 1.0,doubleTwo = 2.0
swapTwoValues(&doubleOne, &doubleTwo)
print("One=\(doubleOne),Two=\(doubleTwo)")
//打印:One=2.0,Two=1.0

泛型类型

除了泛型函数,Swift还允许你定义泛型类型。这些自定义类、结构体和枚举可以适用于任何类型,类似于 Array 和 Dictionary。下面示例代码展示了使用结构体泛型实现栈集合类型。

struct Stack<Element> {
    var items = [Element]()
     mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
    func toString() {
        for item in items {
            print("\(item)",terminator:",")
        }
    }
}

var stack = Stack<String>()
stack.push("东")
stack.push("西")
stack.push("南")
stack.push("北")
stack.toString()
print()
stack.pop()
stack.toString()
print()
stack.pop()
stack.pop()
stack.toString()

代码执行结果如下图所示。

类型约束

有的时候如果能将使用在泛型函数和泛型类型中的类型添加一个特定的类型约束,将会是非常有用的。类型约束可以指定一个类型参数必须继承自指定类,或者符合一个特定的协议或协议组合。类型约束语法如下。

func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
    // 这里是泛型函数的函数体部分
}

下面代码演示在某个数组中查找某个元素的位置,如果数组中不存在该元素,则返回nil。

func findIndex<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
    for (index, value) in array.enumerated() {
        if value == valueToFind {
            return index
        }
    }
    return nil
}

var arr = ["北京","上海","广州","深圳"]

let pos = findIndex(of: "广州", in: arr)

if let p = pos {
    print("在位置\(p)找到元素'广州'")
}else{
    print("没有找到元素'广州'")
}

let pos1 = findIndex(of: "南京", in: arr)

if let p = pos1 {
    print("在位置\(p)找到元素'南京'")
}else{
    print("没有找到元素'南京'")
}

代码执行结果如下图所示。

示例代码

https://github.com/99ios/23.20