美文网首页
swift泛型整理

swift泛型整理

作者: 悃破 | 来源:发表于2017-10-17 18:25 被阅读31次

swift泛型知识主要包括:泛型函数、泛型协议、泛型类型、泛型约束。

一、泛型函数。

如:一个交换两个变量值的函数。

//交换两个Int类型
    func swapTwoIntValue( a: inout Int, b: inout Int) {
        let tempValue = a
        a = b
        b = tempValue
    }

如果要交换两个String类型的,就需要再写一个函数,也就是说交换每种类型都要写一个函数,比较麻烦。而使用泛型一个函数就搞定了。

//使用泛型
    func swapTwoValues <T>( a: inout T, b: inout T) {
        let tempValue = a
        a = b
        b = tempValue
    }
//存在swap(_:_:)函数,可以直接使用。

二、泛型协议(关联类型)

如定义一个协议

protocol Stackable{
    // 声明一个关联类型,使用associatedtype关键字
    associatedtype ItemType
    mutating func push(item:ItemType)
    mutating func pop() -> ItemType?
}

关联类型为协议中的某个类型提供了一个占位名(或者说别名),其代表的实际类型在协议被采纳时才会被指定。你可以通过 associatedtype 关键字来指定关联类型。
使用:

struct IntStack: Stackable {
    typealias ItemType = Int
    var items = [Int]()
    mutating func push(item: Int) {
        items.append(item)
    }
    
    mutating func pop() -> Int? {
        if items.count == 0 {
            return nil
        }
        return items.removeLast()
    }
}

由于 Swift 的类型推断,你实际上不用在 IntStack 的定义中声明 ItemType 为 Int。因为 IntStack 符合 Stackable 协议的所有要求,Swift 只需通过 push(_:) 方法的 item 参数类型和下标返回值的类型,就可以推断出 ItemType 的具体类型。事实上,如果你在上面的代码中删除了 typealias ItemType = Int 这一行,一切仍旧可以正常工作,因为 Swift 清楚地知道 ItemType 应该是哪种类型。

三、泛型类型

如:定义一个Stack实现push、pop操作。

1、一个非泛型( Int)的栈

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

上面的 IntStack 结构体只能用于 Int 类型,如果是其他类型只能再定义另一个Stack了。

2、泛型 Stack 结构体

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

四、泛型约束

泛型约束主要分为:继承约束、协议约束、条件约束。

1、继承约束。

泛型类型必须是某个类的子类类型
格式:

func 函数名<泛型: 继承父类>(参数列表) -> 返回值 {
    // 函数体,泛型类型是某个类的子类类型
     }

如,有三个类,Animal、Dog、Cat,Dog、Cat继承于Animal。它们都有一个run的函数。

class Animal {
    // 动物都会跑
    func run() {
        print("Animal run")
    }
}

class Dog :Animal {
    override func run() {  // 重写父类方法
        print("Dog run")
    }
}

class Cat :Animal {
    override func run() {
        print("Cat run")
    }
}

使用:

func test() {
        let dog = Dog()
        animalRunPrint(animal: dog)
      
       let cat = Cat()
        animalRunPrint(animal: cat)
      //传的参数需要是Animal或其子类。
    }

//继承约束
    func animalRunPrint<T:Animal>(animal:T) {
        animal.run()  // 继承了Animal类的子类都有run方法可以调用
    }

2、协议约束

泛型类型必须遵循某些协议。
格式:

func 函数名<泛型: 协议>(参数列表) -> 返回值 {
     // 函数体,泛型类型遵循某些协议
     }

如:获取一个元素在数组里的索引。

//协议约束
    func findIndex<T: Equatable>(array: [T], valueToFund: T) -> Int? {
        var index = 0
        for value in array {
            if value == valueToFund {
                return index
            }
            index += 1
        }
        return nil
    }

使用:

func test() {
        let doubleIndex = findIndex(array: [1.0,4.9,3.2], valueToFund: 3.0)
        print("doubleIndex = \(String(describing: doubleIndex))")
    }

3、条件约束

泛型类型必须满足某种条件
格式:

func 函数名<泛型1, 泛型2 where 条件>(参数列表) -> 返回值 {
     // 函数体,泛型类型满足某些条件
     }

如:声明一个协议Stackable,创建了一个结构体Stack,如下

protocol Stackable{
    // 声明一个关联类型,使用typealias关键字
    associatedtype ItemType
    mutating func push(item:ItemType)
    mutating func pop() -> ItemType
}

struct Stack<T>:Stackable{
    var store = [T]()
    mutating func push(item:T){  
      // 实现协议的push方法要求
        store.append(item)
    }
    mutating func pop() -> T {   
      // 实现协议的pop方法要求
        return store.removeLast()
    }
}

使用:

    func test() {
        // 创建Stack结构体,泛型类型为String
        var stackOne = Stack<String>()
        stackOne.push(item: "hello")
        stackOne.push(item: "swift")
        stackOne.push(item: "world")
        var stackTwo = Stack<String>()
        pushItemOneToTwo(stackOne: &stackOne, stackTwo: &stackTwo)
    }
//条件约束
    // 添加泛型条件约束,C1和C2必须遵循Stackable协议,而且C1和C2包含的泛型类型要一致
    func pushItemOneToTwo<C1: Stackable, C2: Stackable>( stackOne: inout C1, stackTwo: inout C2)
        where C1.ItemType == C2.ItemType
    { 
// 因为C1和C2都遵循了Stackable协议,才有ItemType属性可以调用
        let item = stackOne.pop()
        stackTwo.push(item: item)
    }

参考文章:
Swift 中的泛型
Swift学习之泛型
swift3.0教程-泛型

相关文章

  • swift泛型整理

    swift泛型知识主要包括:泛型函数、泛型协议、泛型类型、泛型约束。 一、泛型函数。 如:一个交换两个变量值的函数...

  • Swift-泛型笔记

    Swift 泛型 Swift 提供了泛型让你写出灵活且可重用的函数和类型。 Swift 标准库是通过泛型代码构建出...

  • [ WWDC2018 ] - Swift 泛型 Swift Ge

    Swift 泛型历史 我们首先来回顾一下 Swift 中对于泛型支持的历史变更,看看现在在 Swift 中,泛型都...

  • Swift 运用协议泛型封装网络层

    Swift 运用协议泛型封装网络层 Swift 运用协议泛型封装网络层

  • 2021-12-01

    swift5基本语法-泛型函数和泛型类型 Swift中泛型可以将类型参数化,提高代码复用率,减少代码量。 一、泛型...

  • swift 泛型

    Swift-泛型学习和实例总结 - Mazy's Blog - CSDN博客 Swift中的泛型 - 简书

  • 使用Web浏览器编译Swift代码,及Swift中的泛型

    使用Web浏览器编译Swift代码,及Swift中的泛型 使用Web浏览器编译Swift代码,及Swift中的泛型

  • 【Swift】泛型常见使用

    1、Swift泛型4种 泛型函数泛型类型泛型协议泛型约束 2、泛型约束3种 继承约束:泛型类型 必须 是某个类的子...

  • OneDayOneSwift[23] - Generics

    泛型是 Swift 的强大特性之一,许多 Swift 标准库是通过泛型代码构建的。事实上,泛型的使用贯穿了整本语言...

  • Swift和OC的区别

    Swift和OC的区别? 1、Swift没有地址和指针的概念 2、Swift对数据类型要求极为严谨 3、泛型,泛型...

网友评论

      本文标题:swift泛型整理

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