import Foundation
/*泛型所解决的问题*****************************************************/
//这里是一个标准的,非泛型函数 swapTwoInts,用来交换两个Int值:
func swapTwoInts(inout a: Int,inout _ b: Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt,&anotherInt)
print("someInt is now \(someInt),and anotherInt is now \(anotherInt)")
// 输出 "someInt is now 107,and anotherInt is now 3"
//swapTwoInts(_:_:) 函数是非常有用的,但是它只能交换 Int 值,如果你想要交换两个 String 或者 Doubl e,就不得不写更多的函数,如 swapTwoStrings 和 swapTwoDoubles(_:_:),如同如下所示:
func swapTwoStrings(inout a: String,inout _ b: String) {
let temporaryA = a
a = b
b = temporaryA
}
func swapTwoDoubles(inout a: Double,inout _ b: Double) {
let temporaryA = a
a = b
b = temporaryA
}
//你可能注意到 swapTwoInts 、 swapTwoStrings 和 swapTwoDoubles(_:_:) 函数功能都是相同的,唯一不同之处就在于传入的变量类型不同,分别是 Int 、 String 和 Double 。
//注意: 在所有三个函数中,a 和 b 的类型是一样的。如果 a 和 b 不是相同的类型,那它们俩就不能互换 值。Swift 是类型安全的语言,所以它不允许一个 String 类型的变量和一个 Double 类型的变量互相交换 值。如果一定要做,Swift 将报编译错误。
/*泛型函数*****************************************************/
func swapTwoValues<T>(inout a:T,inout _ b:T) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt1 = 3
var anotherInt1 = 107
swapTwoValues(&someInt1,&anotherInt1)
print("someInt1 is now \(someInt1),and anotherInt1 is now \(anotherInt1)")
// someInt 现在等于 107,anotherInt 现在等于 3
var someString = "hello"
var anotherString = "world"
swapTwoValues(&someString,&anotherString)
print("someInt is now \(someString),and anotherInt is now \(anotherString)")
// someString 现在等于 "world",anotherString 现在等于 "hello"
/*类型参数*****************************************************/
/*命名类型参数*****************************************************/
//如果你使用多个参数定义更复杂的泛型函数或泛型类型,那么使用更多的描述类型参数是非常有用的。例如,Swi ft 字典(Dictionary)类型有两个类型参数,一个是键,另外一个是值。如果你自己写字典,你或许会定义这两 个类型参数为 Key和 Value,用来记住它们在你的泛型代码中的作用。
//注意 请始终使用大写字母开头的驼峰式命名法(例如 T 和 Key )来给类型参数命名,以表明它们是类型的占 位符,而非类型值。
/*泛型类型*****************************************************/
struct IntStack {
var items = [Int]()
mutating func push(item:Int){
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
}
struct Stack<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
//T 定义了一个名为“某种类型T”的节点提供给后来用。这种将来类型可以在结构体的定义里任何地方表示 为“T”。在这种情况下,T 在如下三个地方被用作节点:
//? 创建一个名为 items 的属性,使用空的T类型值数组对其进行初始化;
//? 指定一个包含一个参数名为 item 的 push(_:) 方法,该参数必须是T类型;
//? 指定一个 pop 方法的返回值,该返回值将是一个T类型值。
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
// 现在栈已经有4个string了
let fromTheTop = stackOfStrings.pop()
print("\(stackOfStrings)")
// fromTheTop 等于 "cuatro",现在栈中还有3个string
/*扩展一个泛型类型*****************************************************/
extension Stack {
var topItem: T? {
return items.isEmpty ? nil : items[items.count - 1]
}
}
//topItem 属性会返回一个 T 类型的可选值。当栈为空的时候,topItem 将会返回 nil ;当栈不为空的时候,Item 会返回 items 数组中的最后一个元素。
if let topItem = stackOfStrings.topItem {
print("The top item on the stack is \(topItem).")
}
// 输出 "The top item on the stack is tres."
/*类型约束*****************************************************/
//func someFunction<T: SomeClass,U: SomeProtocol>(someT: T,someU: U) {
// // 这里是函数主体
//}
//这里有个名为 findStringIndex 的非泛型函数,该函数功能是去查找包含一给定 String 值的数组。若查找到匹配 的字符串,findStringIndex(_:_:) 函数返回该字符串在数组中的索引值( Int ),反之则返回 nil :
func findStringIndex(array: [String],_ valueToFind: String) -> Int? {
for(index,value) in array.enumerate() {
if value == valueToFind {
return index
}
}
return nil
}
let strings = ["cat","dog","llama","parakeet","terrapin"]
if let foundIndex = findStringIndex(strings,"llama") {
print("The index of llama is \(foundIndex)")
}
// 输出 "The index of llama is 2"
func findIndex<T:Equatable>(array:[T],_ valueToFind:T) -> Int? {
for(index,value) in array.enumerate() {
if value == valueToFind {
return index
}
}
return nil
}
let doubleIndex = findIndex([3.14159,0.1,0.25],9.3)
print("索引号是\(doubleIndex)")
// doubleIndex is an optional Int with no value,because 9.3 is not in the array
let stringIndex = findIndex(["Mike","Malcolm","Andrea"],"Andrea")
print("索引号是\(stringIndex)")
// stringIndex is an optional Int containing a value of 2
/*关联类型*****************************************************/
protocol Container {
typealias ItemType
mutating func append(item: ItemType)
var count: Int{ get }
subscript(i: Int) -> ItemType{ get }
}
struct IntStack2: 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) -> Int {
return items[i]
}
}
struct Stack2<T>: Container {
// original Stack<T> implementation
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
/*Where 语句*****************************************************/
//下面的例子定义了一个名为 allItemsMatch 的泛型函数,用来检查两个Container实例是否包含相同顺序的相同 元素。如果所有的元素能够匹配,那么返回一个为 true 的 Boolean 值,反之则为 false。
func allItemsMatch<C1:Container,C2:Container
where C1.ItemType == C2.ItemType,C1.ItemType: Equatable>
(someContainer: C1,anotherContainer: C2) -> Bool {
// 检查两个Container的元素个数是否相同
if someContainer.count != anotherContainer.count {
return false
}
// 检查两个Container相应位置的元素彼此是否相等
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
// 如果所有元素检查都相同则返回true
return true
}
var stackOfStrings2 = Stack2<String>()
stackOfStrings2.push("uno")
stackOfStrings2.push("dos")
stackOfStrings2.push("tres")
var arrayOfStrings2 = ["uno","dos","tres"]
//if allItemsMatch(stackOfStrings2,arrayOfStrings2) {
// print("All items match.")
//} else {
// print("Not all items match.")
//}
// 输出 "All items match."
//上面的例子创建一个 Stack 单例来存储 String,然后压了三个字符串进栈。这个例子也创建了一个 Array 单 例,并初始化包含三个同栈里一样的原始字符串。即便栈和数组是不同的类型,但它们都遵循 Container 协 议,而且它们都包含同样的类型值。因此你可以调用 allItemsMatch(_:_:) 函数,用这两个容器作为它的参数。在 上面的例子中,allItemsMatch(_:_:) 函数正确的显示了这两个容器的所有元素都是相互匹配的。
原文链接:https://www.f2er.com/swift/324991.html