无规矩不成方圆

2021-12-06  本文已影响0人  凉风起君子意如何

Swift里面有个很强大的特性叫泛型。

什么是泛型?

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

泛型的使用场景

文中给出了两个经典的例子:交换两个变量的值和栈的操作。

首先我们看交换两个Int类型变量的值:

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

很简单,假若现在让你交换两个Double或String类型的值呢。若没泛型,我们是不是要写多个函数或在一个函数里面要写多个if判断来支持,这样一来显得既冗余也不清晰,也不简洁。

我们再来看看栈的操作:(以Int型栈举例)

struct IntStack {
    var items: [Int] = []
    mutating func push(_ item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
}

也很简单,但现在让你对String或Double类型的集合进行相关栈操作。你又该怎么做,是不是也是要和上面一样。很麻烦对吧。


上面两个例子都能很好的用泛型来解决,代码如下:

 // 泛型 交换两个值; T为占位符类型名;T所代表的类型由传入的值的类型推断出来
    public static func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
        let temp = a
        a = b
        b = temp
    }

struct Stack<Element> {
    var items: [Element] = []
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

泛型的类型约束

上面两个经典例子充分说明泛型的妙用,那泛型是不是没有任何约束了,在任何场景下都能给任何类型使用呢?答案是NO。有的场景是需要约束的,就像我们现实生活中一样,自由其实相对的,不管是开车等红绿灯,还是人多买东西的时候要排队...至少现实中的一切自由都是建立你所处的国家法律之上的。正应了那句话--无规矩不成方圆。

现在让我们来看个例子,通过一个函数找出数组中某个值的索引。(例如String数组)

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

将它支持泛型是这样的:

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

但当你敲完代码会发现,编译报错了。是的不是所有的类型都可以用等式符比较,一些自定义类或结构体,若没有遵循Equatable协议,是无法进行等式比较的。


添加泛型约束,改成如下OK

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

猜你喜欢

热点阅读