《swift2.0 官方教程中文版》 第2章-23泛型


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")

// 现在栈已经有4string

let fromTheTop = stackOfStrings.pop()

print("\(stackOfStrings)")

// fromTheTop 等于 "cuatro", 现在栈中还有3string




/*扩展一个泛型类型*****************************************************/

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(_:_:) 函数正确的显示了这两个容器的所有元素都是相互匹配的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值