Swift_学习笔记_泛型
来源:互联网 发布:linux查找文件内容 编辑:程序博客网 时间:2024/05/22 00:23
- 泛型可以使代码更加简洁,避免代码重复,类型检查更加严格。
- 泛型是根据需求定义的,适用于任何类型的,灵活且可重用的函数和类型。
- 避免重复的代码,以一种清晰和抽象的方法来表达代码的意图。
- 占位符的位置在函数名、结构体名等名称的后面,紧随名称。例如:
swapTwoValues<T>
。
泛型函数
- 可以使用占位类型名字(通常使用字母T来表示)来替代实际类型名(Int等)。
- 虽然没有强调参数类型是哪一种,但是参数的类型必定是相同的。
func swapTwoValues<T>(_ left:inout T, _ right:inout T){ let temp = left left = right right = temp}var one = 20var two = 30swapTwoValues(&one, &two)print(one) // 30
- 也支持多个类型参数,命名在尖括号内,用逗号隔开。
func swapTwoValues<T,S>(_ left:inout T, _ right:inout T,center:S){ print("\(center)") let temp = left left = right right = temp}var one = 20var two = 30swapTwoValues(&one, &two, center: "test")print(one)
- 如果使用多个类型参数,那么就需要更多的描述类型参数。例如字典的键值。在命名时,使用大写字母开头的驼峰命名法来类型参数命名,例如:
KeyType
,以表明这些是类型的占位符,而不是类型值。
泛型类型
- 泛型类型的结构体:
struct Stack<T>{ var items = [T]() mutating func push(item:T){ items.append(item) } mutating func pop() -> T{ return items.removeLast() }}var oneStack = Stack<String>()oneStack.push(item: "first")oneStack.push(item: "second")oneStack.push(item: "Third")oneStack.push(item: "Four")
- 在声明时,需要确认类型参数的类型。
扩展泛型类型
- 如果扩展一个泛型,不需要额外提供类型参数。因为可以从原来的类或者结构体重使用原来定义的泛型对象T。
- 代码示例:
extension Stack { var topItem:T?{ return items.isEmpty ? nil : items[items.count - 1] }}print(oneStack.topItem!) // Four
类型约束
- 类似于字典的键值必须是可哈希化的,这就是一种类型约束。
- 当创建自定义泛型类型时,可以定义你自己的类型约束。
- 这些约束要支持泛型编程的强力特征中的多数。
- 抽象概念如可哈希化具有的类型特征是根据它们的概念特征来界定的,而不是它们的直接类型特征。
类型约束语法
- 可以在类型参数后面添加类型约束,通过冒号分割,来作为类型参数链的一部分。
- 代码示例:
class SomeClass{}protocol SomePotocol{}func someFunction<T:SomeClass,U:SomePotocol>(someT:T,someU:U){ // someT 必须是SomeClass类对象或者子类对象 // someU 必须是SomePotocol的实现者}
类型约束行为
func findIndex<T>(array:[T],valueOfFind:T) -> Int?{ for (index,value) in array.enumerated() { if value == valueOfFind { // error: binary operator '==' cannot be applied to two 'T' operands return index } } return nil}
- 由于上述例子,类型参数没有任何约束,当然也不遵守
Equatable
协议,因此也就不能进行比较。 - 对类型参数添加约束行为
Equatable
,如下述代码所示:
func findIndex<T:Equatable>(array:[T],valueOfFind:T) -> Int?{ for (index,value) in array.enumerated() { if value == valueOfFind { return index } } return nil}findIndex(array: [3.0,4.0,5.0], valueOfFind: 4.0)// 输出1
关联类型
- 关键字
associatedtype
,关联类型。 - 关键字
typealias
,类型别名。
关联类型行为
代码示例:
protocol Container{ associatedtype ItemType mutating func append(_ item:ItemType) var count:Int{ get} 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 别名 typealias ItemType = Int mutating func append(_ item:ItemType){ self.push(item: item) } var count: Int{ return items.count } subscript (i:Int)->Int{ return items[i] }}struct Stack<T>:Container{ var items = [T]() mutating func push(item:T){ items.append(item) } mutating func pop()->T{ return items.removeLast() } typealias ItemType = T mutating func append(_ item: T) { self.push(item: item) } var count: Int{ return items.count } subscript(i:Int)->T{ return items[i] }}
扩展一个存在的类型为指定关联类型
- 由于数组实现了上述协议内的所有内容,所以定义了扩展之后,可以将
Array
当做Container
来使用。 - 实现空扩展如下:
extension Array:Container{}
Where语句
- 确保你定义关于类型参数的需求和泛型函数或类型有关联。
Where
之前,函数的声明。Where
之后,某个类型参数的要求,以及类型参数之间的关系。- 代码示例:
func allItemsMatch<C1:Container,C2:Container>(someContainer:C1,anotherContainer:C2)->Bool where C1.ItemType == C2.ItemType,C1.ItemType:Equatable{ if someContainer.count != anotherContainer.count { return false } for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false } } return true}
- 上述代码的类型参数为:
<C1:Container,C2:Container> 函数的参数以及返回值 where C1.ItemType == C2.ItemType,C1.ItemType:Equatable>
C1
必须实现Container
协议。C2
必须实现Container
协议。C1
的ItemType
与C2
的ItmeType
相同,C1.ItemType == C2.ItemType
。C1
的ItemType
必须实现Equatable
协议,C1.ItemType:Equatable
。
阅读全文
0 0
- Swift_学习笔记_泛型
- Swift_学习笔记_基础知识
- Swift_学习笔记_类
- Swift_学习笔记_继承
- Swift_学习笔记_协议
- Swift_学习笔记_字符串、数组、字典
- Swift_学习笔记_自动引用计数
- Swift_学习笔记_类型转换
- Swift_学习笔记_运算符重载
- Swift_学习笔记_闭包
- Swift_学习笔记_调用ObjectiveC方法
- Swift_学习笔记_控制语句和函数
- Swift_学习笔记_枚举和结构体
- Swift_泛型
- Swift_运算符_流程控制
- 管理学_学习笔记
- 学习笔记_容器
- 学习笔记_堆
- 【HDU】 1003 Max Sum(最大连续子序列和)
- 在Spring MVC controller中配切点
- 基于Zigbee温湿度监测系统
- 数组查找元素
- shell脚本——判断文件的属性、内容、、
- Swift_学习笔记_泛型
- 知道别人的端口,如何看出端口有什么漏洞
- redis配置详解
- Spring源码阅读(七)—AOP创建代理
- eclipse将Java project 修改为Dynamic Web project
- 父类的static属性和方法
- Word教程Spire.Doc 教程:在Word文档中转换文件格式
- c++小数点后几位、有效位数、格式化输出
- Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null objec