美文网首页
22.泛型 Generics Swift官方文档——版纳的笔记

22.泛型 Generics Swift官方文档——版纳的笔记

作者: KevinFromChina | 来源:发表于2018-03-29 18:38 被阅读0次
    //: Playground - noun: a place where people can play
    
    import UIKit
    
    // # 泛型解决的问题
    /*
    func swapTwoInts(_ a: inout Int, _ b: inout Int) {
        let temporaryA = a
        a = b
        b = temporaryA
    }
    var someInt = 3
    var anotherInt = 107
    swapTwoInts(&someInt, &anotherInt)
    print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
    */
    
    // # 泛型函数
    func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
        let temporaryA = a
        a = b
        b = temporaryA
    }
    var someInt = 3
    var anotherInt = 107
    swapTwoValues(&someInt, &anotherInt)
    var someString = "hello"
    var anotherString = "world"
    swapTwoValues(&someString, &anotherString)
    // trick: swap(_:_:)Swift库已实现
    
    // # 类型形式参数
    // 类型形式参数指定并且命名一个占位符类型,紧挨着写在函数名后面的一对尖括号里(比如 <T> )
    
    // # 命名类型形式参数
    // 用大写驼峰命名法,表明是一个占位符
    
    // # 泛型类型
    struct Stack<Element> {
        var items = [Element]()
        mutating func push(_ item: Element) {
            items.append(item)
        }
        mutating func pop() -> Element {
            return items.removeLast()
        }
        init() {
            // just do nothing here
        }
        init(items: [Element]) {
            self.items = items
        }
    }
    var stackOfStrings = Stack<String>()
    stackOfStrings.push("uno")
    stackOfStrings.push("dos")
    stackOfStrings.push("tres")
    stackOfStrings.push("cuatro")
    let fromTheTop = stackOfStrings.pop()
    
    var stackOfInts = Stack(items: [1, 2, 7]) // '<Int>' can be inferred so is omittd.
    
    
    // *** 泛型的类可以被继承为非泛型
    let view = UIView()
    let label = UILabel()
    let topConstraint = label.topAnchor.constraint(equalTo: view.topAnchor)
    // YAnchor is a subclass of anchor. Anchor is a generic class.
    // 参见泛型1.playground
    
    
    // # 扩展一个泛型类型
    extension Stack {
        var topItem: Element? {
            return items.isEmpty ? nil : items[items.count - 1]
        }
    }
    if let topItem = stackOfStrings.topItem {
        print("The top item on the stack is \(topItem).")
    }
    
    // # 类型约束
    // For example, Hashable: a type that provides an integer hash value.
    /*
    func findIndex(ofString valueToFind: String, in array: [String]) -> Int? {
        // trick: array.enumerated() 返回了一个元组的数组,用for-in提取每个元素(n, x)
        // 若为数组,n是从零开始的序列,x是对应的元素
        // 若为字符串,n是从零开始的序列,x是对应的字符
        for (index, value) in array.enumerated() {
            if value == valueToFind {
                return index
            }
        }
        return nil
    }
    let strings = ["cat", "dog", "llama", "parakeet", "terrapin"]
    if let foundIndex = findIndex(ofString: "llama", in: strings) {
        print("The index of llama is \(foundIndex)")
    }
    */
    func findIndex<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
        for (index, value) in array.enumerated() {
            if value == valueToFind {
                return index
            }
        }
        return nil
    }
    let doubleIndex = findIndex(of: 9.3, in: [3.3424, 0.1, 0.25])
    let stringIndex = findIndex(of: "Andrea", in: ["Mike", "Malcolm", "Andrea"])
    
    // # 关联类型
    protocol Container {
        associatedtype ItemType // ItemType 是一个占位符
        mutating func append(_ item: ItemType)
        var count: Int { get }
        // trick: 下标在协议中的使用
        subscript(i: Int) -> ItemType { get }
    }
    struct IntStack: Container {
        var items = [Int]()
        mutating func push(_ item: Int) {
            items.append(item)
        }
        mutating func pop() -> Int {
            return items.removeLast()
        }
        typealias ItemType = Int // ???
        mutating func append(_ item: Int) {
            self.push(item)
        }
        var count: Int {
            return items.count
        }
        subscript(i: Int) -> Int {
            return items[i]
        }
    }
    struct StackAgain<Element>: Container {
        var items = [Element]()
        mutating func push(_ item: Element) {
            items.append(item)
        }
        mutating func pop() -> Element {
            return items.removeLast()
        }
        mutating func append(_ item: Element) {
            self.push(item)
        }
        var count: Int {
            return items.count
        }
        subscript(i: Int) -> Element {
            return items[i]
        }
    }
    // 扩展现有类型来指定关联类型
    extension Array: Container {}
    // now we can use an Array as a Container type.
    
    // # 泛型where分句
    // where语句,冒号+协议语句都是对泛型类型的限制
    func allItemsMatch<C1: Container, C2: Container>(_ someContainer: C1, _ anotherContainer: C2) -> Bool where C1.ItemType == C2.ItemType, C1.ItemType: Equatable {
        
        // Check that both containers contain the same number of items.
        if someContainer.count != anotherContainer.count {
            return false
        }
        
        // Check each pair of items to see if they are equivalent.
        for i in 0..<someContainer.count {
            if someContainer[i] != anotherContainer[i] {
                return false
            }
        }
        
        // All items match, so return true.
        return true
    }
    var stackOfStringsAgain = StackAgain<String>()
    stackOfStringsAgain.push("uno")
    stackOfStringsAgain.push("dos")
    stackOfStringsAgain.push("tres")
    var arrayOfStrings = ["uno", "dos", "tres"]
    if allItemsMatch(stackOfStringsAgain, arrayOfStrings) {
        print("All items match.")
    } else {
        print("Not all items match.")
    }
    
    // # 带有泛型Where分句的扩展
    extension Stack where Element: Equatable {
        func isTop(_ item: Element) -> Bool {
            // trick: .last如果为空返回nil,否则返回包裹最后一个元素的可选项
            guard let topItem = items.last else {
                return false
            }
            return topItem == item
        }
    }
    if stackOfStrings.isTop("tres") {
        print("Top element is tres.")
    } else {
        print("Top element is something else.")
    }
    
    struct NotEquatable { }
    var notEquatableStack = Stack<NotEquatable>()
    let notEquatableValue = NotEquatable()
    notEquatableStack.push(notEquatableValue)
    // Error when: notEquatableStack.isTop(notEquatableValue)
    
    extension Container where ItemType: Equatable {
        func startsWith(_ item: ItemType) -> Bool {
            return count >= 1 && self[0] == item
        }
    }
    if [9, 9, 9].startsWith(42) {
        print("Starts with 42.")
    } else {
        print("Starts with something else.")
    }
    
    extension Container where ItemType == Double {
        func average() -> Double {
            var sum = 0.0
            for index in 0..<count {
                sum += self[index]
            }
            return sum / Double(count)
        }
    }
    print([1260.0, 1200.0, 98.6, 37.0].average())
    // 注意: 多要求用逗号隔开
    
    // # 关联类型的泛型where分句
    protocol NewContainer {
        associatedtype Item
        mutating func append(_ item: Item)
        var count: Int { get }
        subscript(i: Int) -> Item { get }
        
        associatedtype Iterator: IteratorProtocol where Iterator.Element == Item
        func makeIterator() -> Iterator
    }
    protocol ComparableContainer: NewContainer where Item: Comparable { }
    
    // # 泛型下标
    extension NewContainer {
        subscript<Indices: Sequence>(indices: Indices) -> [Item] where Indices.Iterator.Element == Int {
            var result = [Item]()
            for index in indices {
                result.append(self[index])
            }
            return result
        }
    }
    

    相关文章

      网友评论

          本文标题:22.泛型 Generics Swift官方文档——版纳的笔记

          本文链接:https://www.haomeiwen.com/subject/ovlvcftx.html