Swift_学习笔记_泛型
2017-09-01 17:15
483 查看
泛型可以使代码更加简洁,避免代码重复,类型检查更加严格。
泛型是根据需求定义的,适用于任何类型的,灵活且可重用的函数和类型。
避免重复的代码,以一种清晰和抽象的方法来表达代码的意图。
占位符的位置在函数名、结构体名等名称的后面,紧随名称。例如:
虽然没有强调参数类型是哪一种,但是参数的类型必定是相同的。
也支持多个类型参数,命名在尖括号内,用逗号隔开。
如果使用多个类型参数,那么就需要更多的描述类型参数。例如字典的键值。在命名时,使用大写字母开头的驼峰命名法来类型参数命名,例如:
在声明时,需要确认类型参数的类型。
代码示例:
当创建自定义泛型类型时,可以定义你自己的类型约束。
这些约束要支持泛型编程的强力特征中的多数。
抽象概念如可哈希化具有的类型特征是根据它们的概念特征来界定的,而不是它们的直接类型特征。
代码示例:
由于上述例子,类型参数没有任何约束,当然也不遵守
对类型参数添加约束行为
关键字
实现空扩展如下:
代码示例:
上述代码的类型参数为:
泛型是根据需求定义的,适用于任何类型的,灵活且可重用的函数和类型。
避免重复的代码,以一种清晰和抽象的方法来表达代码的意图。
占位符的位置在函数名、结构体名等名称的后面,紧随名称。例如:
swapTwoValues<T>。
泛型函数
可以使用占位类型名字(通常使用字母T来表示)来替代实际类型名(Int等)。虽然没有强调参数类型是哪一种,但是参数的类型必定是相同的。
func swapTwoValues<T>(_ left:inout T, _ right:inout T){ let temp = left left = right right = temp } var one = 20 var two = 30 swapTwoValues(&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 = 20 var two = 30 swapTwoValues(&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。
相关文章推荐
- swift学习笔记之泛型
- iOS学习笔记47-Swift(七)泛型
- iOS学习笔记47-Swift(七)泛型
- iOS学习笔记47-Swift(七)泛型
- swift学习笔记5——其它部分(自动引用计数、错误处理、泛型...)
- swift学习笔记->泛型
- swift学习笔记之-泛型
- Swift学习笔记22——泛型(Generics)
- [Swift]:快速学习笔记5 扩展和泛型
- swift学习笔记(20)- 泛型
- Generics Types 泛型学习笔记<二>
- 【Swift基础】Swift 4.0学习笔记
- Swift_学习笔记_控制语句和函数
- JAVA学习笔记35——泛型1:泛型的简介以及使用
- 【Swift】学习笔记(三)——字符和字符串
- Swift学习笔记5——流程控制语句
- Swift学习笔记(二)——函数
- Android(java)学习笔记92:泛型高级之通配符
- 学习Swift笔记 (四)
- 学校学习ios教程笔记,第四节swift中可变数组和不可变数组以及元组的概念与操作