Swift学习之泛型

作者: coderhlt | 来源:发表于2020-01-14 17:21 被阅读0次
    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()
    }
    

    相关文章

      网友评论

        本文标题:Swift学习之泛型

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