Swift里泛型

本文详细介绍了Swift中的泛型,包括泛型解决的问题、泛型函数、类型参数、命名类型参数、泛型类型、泛型扩展、类型约束、关联类型及其实践、泛型Where语句及其应用,以及泛型下标等内容,旨在帮助读者理解并熟练运用Swift泛型进行编程。
摘要由CSDN通过智能技术生成

目录

泛型解决的问题(不同类型数据进行相同运算的问题?)

泛型函数(没有具体的实际类型,会根据使用传入值的类型推导出来)

类型参数 ( =占位符类型名T ?

命名类型参数 (与函数有关系可命名有意义参数, 无关用字符T,U,V

泛型类型(Stack 栈类型示例)

泛型扩展 (添加Extension和实现,类似OC的Cartegory)

类型约束 (对入参限制为指定类、遵循特定的协议或协议组合

类型约束语法 (  

类型约束实践

关联类型 (associatedType 关键字指定关联类型)

关联类型实践 (保证protocol操作的类型一致性)

扩展现有类型来指定关联类型

给关联类型添加约束

在关联类型约束里使用协议(where 关键字对关联类型约束进行约束)

泛型 Where 语句(遵循协议或固定类型)

具有泛型 Where子句的扩展 (extension里用where对类型扩展和约束

具有泛型 Where子句的关联类型(protocol里泛型使用where约束?)

泛型下标


泛型是 Swift 最强大的特性之一,很多 Swift 标准库是基于泛型代码构建的。实际上,即使你没有意识到,你也一直在语言指南中使用泛型。例如,Swift 的 Array 和 Dictionary 都是泛型集合。你可以创建一个 Int 类型数组,也可创建一个 String 类型数组,甚至可以是任意其他 Swift 类型的数组。

泛型解决的问题(不同类型数据进行相同运算的问题?)

// Int 类型的值交换函数
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

// Sting 类型的值交换函数
func swapTwoStrings(_ a: inout String, _ b: inout String) {
    let temporaryA = a
    a = b
    b = temporaryA
}

func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
    let temporaryA = a
    a = b
    b = temporaryA
}

函数体是一样的,唯一的区别是它们接受的参数类型(IntString 和 Double

泛型函数(没有具体的实际类型,会根据使用传入值的类型推导出来)

泛型函数和非泛型函数的另外一个不同之处在于这个泛型函数名(swapTwoValues(_:_:))后面跟着占位类型名(T),并用尖括号括起来(<T>)。这个尖括号告诉 Swift 那个 T 是 swapTwoValues(_:_:) 函数定义内的一个占位类型名,因此 Swift 不会去查找名为 T的实际类型。T 所代表的类型都会由传入的值的类型推断出来。

// 泛型函数 swapTwoValues(_:_:)
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

泛型版本的函数使用占位符类型名(这里叫做 T 。通常使用单个字符来表示,例如 TUV,例如上面演示函数)

swap(_:_:) 函数存在于 Swift 标准库,你可以在你的应用程序中使用它。

类型参数 ( =占位符类型名T ?

上面 swapTwoValues(_:_:) 例子中,占位类型 T 是一个类型参数的例子,类型参数指定并命名一个占位类型,并且紧随在函数名后面,使用一对尖括号括起来(例如 <T>)。

可提供多个类型参数,将它们都写在尖括号中,用逗号分开。<T, U>

命名类型参数 (与函数有关系可命名有意义参数, 无关用字符T,U,V

大多情况下,类型参数具有描述下的名称,例如字典 Dictionary<Key, Value> 中的 Key 和 Value 及数组 Array<Element> 中的 Element,这能告诉阅读代码的人这些参数类型与泛型类型或函数之间的关系。

当它们之间没有有意义的关系时,通常使用单个字符来表示,例如 TUV

泛型类型(Stack<Element> 栈类型示例)

示例:栈的泛型实现 
struct Stack<Element> {
    var items = [Element]()
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

用占位类型参数 Element 这个类型参数包裹在紧随结构体名的一对尖括号里(<Element>)。

使用类似于Array 和 Dictionary

泛型扩展 (添加Extension和实现,类似OC的Cartegory)

原始类型定义中声明的类型参数列表在扩展中可以直接使用,并且这些来自原始类型中的参数名称会被用作原始定义中类型参数的引用。

示例:为Stack 扩展 topItem 方法
extension Stack {

Stack 中已有的类型参数名称 Element,被用在扩展中来表示计算型属性 topItem 的可选类型。
    var topItem: Element? {
        return items.isEmpty ? nil : items[items.count - 1]
    }
}

类型约束 (对入参限制为指定类、遵循特定的协议或协议组合

类型约束指定类型参数必须继承自指定类、遵循特定的协议或协议组合。

例如,Swift 的 Dictionary 类型对字典的键的类型做了些限制。在 字典的描述 中,字典键的类型必须是可哈希(hashable)的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值