ImageVerifierCode 换一换
你正在下载:

22泛型.docx

[预览]
格式:DOCX , 页数:20 ,大小:70.74KB ,
资源ID:28180779      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/28180779.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(22泛型.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

22泛型.docx

1、22泛型The Swift Programming Language 中文版 About the author Questions and Issues Edit and Contribute Introduction 1.欢迎使用 Swifto 1.1.关于 Swifto 1.2.Swift 初见 2.Swift 教程o 2.1.基础部分o 2.2.基本运算符o 2.3.字符串和字符o 2.4.集合类型o 2.5.控制流o 2.6.函数o 2.7.闭包o 2.8.枚举o 2.9.类和结构体o 2.10.属性o 2.11.方法o 2.12.下标脚本o 2.13.继承o 2.14.构造过程o 2

2、.15.析构过程o 2.16.自动引用计数o 2.17.可选链o 2.18.类型转换o 2.19.嵌套类型o 2.20.扩展o 2.21.协议o 2.22.泛型o 2.23.高级操作符 3.语言参考o 3.1.关于语言参考o 3.2.词法结构o 3.3.类型o 3.4.表达式o 3.5.语句o 3.6.声明o 3.7.特性o 3.8.模式o 3.9.泛型参数o 3.10.语法总结 Generated using GitBook翻译:takalard校对:lifedim泛型本页包含内容: 泛型所解决的问题 泛型函数 类型参数 命名类型参数 泛型类型 类型约束 关联类型 Where语句泛型代码可以

3、让你写出根据自我需求定义、适用于任何类型的,灵活且可重用的函数和类型。它的可以让你避免重复的代码,用一种清晰和抽象的方式来表达代码的意图。泛型是 Swift 强大特征中的其中一个,许多 Swift 标准库是通过泛型代码构建出来的。事实上,泛型的使用贯穿了整本语言手册,只是你没有发现而已。例如,Swift 的数组和字典类型都是泛型集。你可以创建一个Int数组,也可创建一个String数组,或者甚至于可以是任何其他 Swift 的类型数据数组。同样的,你也可以创建存储任何指定类型的字典(dictionary),而且这些类型可以是没有限制的。泛型所解决的问题这里是一个标准的,非泛型函数swapTwo

4、Ints,用来交换两个Int值:func swapTwoInts(inout a: Int, inout b: Int) let temporaryA = a a = b b = temporaryA这个函数使用写入读出(in-out)参数来交换a和b的值,请参考写入读出参数。swapTwoInts函数可以交换b的原始值到a,也可以交换a的原始值到b,你可以调用这个函数交换两个Int变量值:var someInt = 3var anotherInt = 107swapTwoInts(&someInt, &anotherInt)println(someInt is now (someInt),

5、and anotherInt is now (anotherInt)/ 输出 someInt is now 107, and anotherInt is now 3swapTwoInts函数是非常有用的,但是它只能交换Int值,如果你想要交换两个String或者Double,就不得不写更多的函数,如swapTwoStrings和swapTwoDoublesfunctions,如同如下所示:func swapTwoStrings(inout a: String, inout b: String) let temporaryA = a a = b b = temporaryAfunc swapTw

6、oDoubles(inout a: Double, inout b: Double) let temporaryA = a a = b b = temporaryA你可能注意到swapTwoInts、swapTwoStrings和swapTwoDoubles函数功能都是相同的,唯一不同之处就在于传入的变量类型不同,分别是Int、String和Double。但实际应用中通常需要一个用处更强大并且尽可能的考虑到更多的灵活性单个函数,可以用来交换两个任何类型值,很幸运的是,泛型代码帮你解决了这种问题。(一个这种泛型函数后面已经定义好了。)注意:在所有三个函数中,a和b的类型是一样的。如果a和b不是相

7、同的类型,那它们俩就不能互换值。Swift 是类型安全的语言,所以它不允许一个String类型的变量和一个Double类型的变量互相交换值。如果一定要做,Swift 将报编译错误。泛型函数泛型函数可以工作于任何类型,这里是一个上面swapTwoInts函数的泛型版本,用于交换两个值:func swapTwoValues(inout a: T, inout b: T) let temporaryA = a a = b b = temporaryAswapTwoValues函数主体和swapTwoInts函数是一样的,它只在第一行稍微有那么一点点不同于swapTwoInts,如下所示:func s

8、wapTwoInts(inout a: Int, inout b: Int)func swapTwoValues(inout a: T, inout b: T)这个函数的泛型版本使用了占位类型名字(通常此情况下用字母T来表示)来代替实际类型名(如Int、String或Double)。占位类型名没有提示T必须是什么类型,但是它提示了a和b必须是同一类型T,而不管T表示什么类型。只有swapTwoValues函数在每次调用时所传入的实际类型才能决定T所代表的类型。另外一个不同之处在于这个泛型函数名后面跟着的占位类型名字(T)是用尖括号括起来的()。这个尖括号告诉 Swift 那个T是swapTwo

9、Values函数所定义的一个类型。因为T是一个占位命名类型,Swift 不会去查找命名为T的实际类型。swapTwoValues函数除了要求传入的两个任何类型值是同一类型外,也可以作为swapTwoInts函数被调用。每次swapTwoValues被调用,T所代表的类型值都会传给函数。在下面的两个例子中,T分别代表Int和String:var someInt = 3var anotherInt = 107swapTwoValues(&someInt, &anotherInt)/ someInt is now 107, and anotherInt is now 3var someString

10、= hellovar anotherString = worldswapTwoValues(&someString, &anotherString)/ someString is now world, and anotherString is now hello注意上面定义的函数swapTwoValues是受swap函数启发而实现的。swap函数存在于 Swift 标准库,并可以在其它类中任意使用。如果你在自己代码中需要类似swapTwoValues函数的功能,你可以使用已存在的交换函数swap函数。类型参数在上面的swapTwoValues例子中,占位类型T是一种类型参数的示例。类型参数指定

11、并命名为一个占位类型,并且紧随在函数名后面,使用一对尖括号括起来(如)。一旦一个类型参数被指定,那么其可以被使用来定义一个函数的参数类型(如swapTwoValues函数中的参数a和b),或作为一个函数返回类型,或用作函数主体中的注释类型。在这种情况下,被类型参数所代表的占位类型不管函数任何时候被调用,都会被实际类型所替换(在上面swapTwoValues例子中,当函数第一次被调用时,T被Int替换,第二次调用时,被String替换。)。你可支持多个类型参数,命名在尖括号中,用逗号分开。命名类型参数在简单的情况下,泛型函数或泛型类型需要指定一个占位类型(如上面的swapTwoValues泛型函

12、数,或一个存储单一类型的泛型集,如数组),通常用一单个字母T来命名类型参数。不过,你可以使用任何有效的标识符来作为类型参数名。如果你使用多个参数定义更复杂的泛型函数或泛型类型,那么使用更多的描述类型参数是非常有用的。例如,Swift 字典(Dictionary)类型有两个类型参数,一个是键,另外一个是值。如果你自己写字典,你或许会定义这两个类型参数为KeyType和ValueType,用来记住它们在你的泛型代码中的作用。注意请始终使用大写字母开头的驼峰式命名法(例如T和KeyType)来给类型参数命名,以表明它们是类型的占位符,而非类型值。泛型类型通常在泛型函数中,Swift 允许你定义你自己

13、的泛型类型。这些自定义类、结构体和枚举作用于任何类型,如同Array和Dictionary的用法。这部分向你展示如何写一个泛型集类型-Stack(栈)。一个栈是一系列值域的集合,和Array(数组)类似,但其是一个比 Swift 的Array类型更多限制的集合。一个数组可以允许其里面任何位置的插入/删除操作,而栈,只允许在集合的末端添加新的项(如同push一个新值进栈)。同样的一个栈也只能从末端移除项(如同pop一个值出栈)。注意栈的概念已被UINavigationController类使用来模拟试图控制器的导航结构。你通过调用UINavigationController的pushViewCo

14、ntroller:animated:方法来为导航栈添加(add)新的试图控制器;而通过popViewControllerAnimated:的方法来从导航栈中移除(pop)某个试图控制器。每当你需要一个严格的后进先出方式来管理集合,堆栈都是最实用的模型。下图展示了一个栈的压栈(push)/出栈(pop)的行为:1. 现在有三个值在栈中;2. 第四个值“pushed”到栈的顶部;3. 现在有四个值在栈中,最近的那个在顶部;4. 栈中最顶部的那个项被移除,或称之为“popped”;5. 移除掉一个值后,现在栈又重新只有三个值。这里展示了如何写一个非泛型版本的栈,Int值型的栈:struct IntS

15、tack var items = Int() mutating func push(item: Int) items.append(item) mutating func pop() - Int return items.removeLast() 这个结构体在栈中使用一个Array性质的items存储值。Stack提供两个方法:push和pop,从栈中压进一个值和移除一个值。这些方法标记为可变的,因为它们需要修改(或转换)结构体的items数组。上面所展现的IntStack类型只能用于Int值,不过,其对于定义一个泛型Stack类(可以处理任何类型值的栈)是非常有用的。这里是一个相同代码的泛型

16、版本:struct Stack var items = T() mutating func push(item: T) items.append(item) mutating func pop() - T return items.removeLast() 注意到Stack的泛型版本基本上和非泛型版本相同,但是泛型版本的占位类型参数为T代替了实际Int类型。这种类型参数包含在一对尖括号里(),紧随在结构体名字后面。T定义了一个名为“某种类型T”的节点提供给后来用。这种将来类型可以在结构体的定义里任何地方表示为“T”。在这种情况下,T在如下三个地方被用作节点: 创建一个名为items的属性,使用

17、空的T类型值数组对其进行初始化; 指定一个包含一个参数名为item的push方法,该参数必须是T类型; 指定一个pop方法的返回值,该返回值将是一个T类型值。当创建一个新单例并初始化时, 通过用一对紧随在类型名后的尖括号里写出实际指定栈用到类型,创建一个Stack实例,同创建Array和Dictionary一样:var stackOfStrings = Stack()stackOfStrings.push(uno)stackOfStrings.push(dos)stackOfStrings.push(tres)stackOfStrings.push(cuatro)/ 现在栈已经有4个strin

18、g了下图将展示stackOfStrings如何push这四个值进栈的过程:从栈中pop并移除值cuatro:let fromTheTop = stackOfStrings.pop()/ fromTheTop is equal to cuatro, and the stack now contains 3 strings下图展示了如何从栈中pop一个值的过程:由于Stack是泛型类型,所以在 Swift 中其可以用来创建任何有效类型的栈,这种方式如同Array和Dictionary。类型约束swapTwoValues函数和Stack类型可以作用于任何类型,不过,有的时候对使用在泛型函数和泛型类型

19、上的类型强制约束为某种特定类型是非常有用的。类型约束指定了一个必须继承自指定类的类型参数,或者遵循一个特定的协议或协议构成。例如,Swift 的Dictionary类型对作用于其键的类型做了些限制。在字典的描述中,字典的键类型必须是可哈希,也就是说,必须有一种方法可以使其被唯一的表示。Dictionary之所以需要其键是可哈希是为了以便于其检查其是否已经包含某个特定键的值。如无此需求,Dictionary既不会告诉是否插入或者替换了某个特定键的值,也不能查找到已经存储在字典里面的给定键值。这个需求强制加上一个类型约束作用于Dictionary的键上,当然其键类型必须遵循Hashable协议(S

20、wift 标准库中定义的一个特定协议)。所有的 Swift 基本类型(如String,Int,Double和Bool)默认都是可哈希。当你创建自定义泛型类型时,你可以定义你自己的类型约束,当然,这些约束要支持泛型编程的强力特征中的多数。抽象概念如可哈希具有的类型特征是根据它们概念特征来界定的,而不是它们的直接类型特征。类型约束语法你可以写一个在一个类型参数名后面的类型约束,通过冒号分割,来作为类型参数链的一部分。这种作用于泛型函数的类型约束的基础语法如下所示(和泛型类型的语法相同):func someFunction(someT: T, someU: U) / function body go

21、es here上面这个假定函数有两个类型参数。第一个类型参数T,有一个需要T必须是SomeClass子类的类型约束;第二个类型参数U,有一个需要U必须遵循SomeProtocol协议的类型约束。类型约束行为这里有个名为findStringIndex的非泛型函数,该函数功能是去查找包含一给定String值的数组。若查找到匹配的字符串,findStringIndex函数返回该字符串在数组中的索引值(Int),反之则返回nil:func findStringIndex(array: String, valueToFind: String) - Int? for (index, value) in e

22、numerate(array) if value = valueToFind return index return nilfindStringIndex函数可以作用于查找一字符串数组中的某个字符串:let strings = cat, dog, llama, parakeet, terrapinif let foundIndex = findStringIndex(strings, llama) println(The index of llama is (foundIndex)/ 输出 The index of llama is 2如果只是针对字符串而言查找在数组中的某个值的索引,用处不是

23、很大,不过,你可以写出相同功能的泛型函数findIndex,用某个类型T值替换掉提到的字符串。这里展示如何写一个你或许期望的findStringIndex的泛型版本findIndex。请注意这个函数仍然返回Int,是不是有点迷惑呢,而不是泛型类型?那是因为函数返回的是一个可选的索引数,而不是从数组中得到的一个可选值。需要提醒的是,这个函数不会编译,原因在例子后面会说明:func findIndex(array: T, valueToFind: T) - Int? for (index, value) in enumerate(array) if value = valueToFind retu

24、rn index return nil上面所写的函数不会编译。这个问题的位置在等式的检查上,“if value = valueToFind”。不是所有的 Swift 中的类型都可以用等式符(=)进行比较。例如,如果你创建一个你自己的类或结构体来表示一个复杂的数据模型,那么 Swift 没法猜到对于这个类或结构体而言“等于”的意思。正因如此,这部分代码不能可能保证工作于每个可能的类型T,当你试图编译这部分代码时估计会出现相应的错误。不过,所有的这些并不会让我们无从下手。Swift 标准库中定义了一个Equatable协议,该协议要求任何遵循的类型实现等式符(=)和不等符(!=)对任何两个该类型进

25、行比较。所有的 Swift 标准类型自动支持Equatable协议。任何Equatable类型都可以安全的使用在findIndex函数中,因为其保证支持等式操作。为了说明这个事实,当你定义一个函数时,你可以写一个Equatable类型约束作为类型参数定义的一部分:func findIndex(array: T, valueToFind: T) - Int? for (index, value) in enumerate(array) if value = valueToFind return index return nilfindIndex中这个单个类型参数写做:T: Equatable,也

26、就意味着“任何T类型都遵循Equatable协议”。findIndex函数现在则可以成功的编译过,并且作用于任何遵循Equatable的类型,如Double或String:let doubleIndex = findIndex(3.14159, 0.1, 0.25, 9.3)/ doubleIndex is an optional Int with no value, because 9.3 is not in the arraylet stringIndex = findIndex(Mike, Malcolm, Andrea, Andrea)/ stringIndex is an optio

27、nal Int containing a value of 2关联类型(Associated Types)当定义一个协议时,有的时候声明一个或多个关联类型作为协议定义的一部分是非常有用的。一个关联类型作为协议的一部分,给定了类型的一个占位名(或别名)。作用于关联类型上实际类型在协议被实现前是不需要指定的。关联类型被指定为typealias关键字。关联类型行为这里是一个Container协议的例子,定义了一个ItemType关联类型:protocol Container typealias ItemType mutating func append(item: ItemType) var cou

28、nt: Int get subscript(i: Int) - ItemType get Container协议定义了三个任何容器必须支持的兼容要求: 必须可能通过append方法添加一个新item到容器里; 必须可能通过使用count属性获取容器里items的数量,并返回一个Int值; 必须可能通过容器的Int索引值下标可以检索到每一个item。这个协议没有指定容器里item是如何存储的或何种类型是允许的。这个协议只指定三个任何遵循Container类型所必须支持的功能点。一个遵循的类型在满足这三个条件的情况下也可以提供其他额外的功能。任何遵循Container协议的类型必须指定存储在其里面

29、的值类型,必须保证只有正确类型的items可以加进容器里,必须明确可以通过其下标返回item类型。为了定义这三个条件,Container协议需要一个方法指定容器里的元素将会保留,而不需要知道特定容器的类型。Container协议需要指定任何通过append方法添加到容器里的值和容器里元素是相同类型,并且通过容器下标返回的容器元素类型的值的类型是相同类型。为了达到此目的,Container协议声明了一个ItemType的关联类型,写作typealias ItemType。这个协议不会定义ItemType是什么的别名,这个信息将由任何遵循协议的类型来提供。尽管如此,ItemType别名提供了一种识

30、别Container中Items类型的方法,并且用于append方法和subscript方法的类型定义,以便保证任何Container期望的行为能够被执行。这里是一个早前IntStack类型的非泛型版本,遵循Container协议:struct IntStack: Container / IntStack的原始实现 var items = Int() mutating func push(item: Int) items.append(item) mutating func pop() - Int return items.removeLast() / 遵循Container协议的实现 typealias ItemType = Int mutating func append(item: Int) self.push(item) var count: Int return items.count subscript(i: Int) - I

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1