跳转至

泛型

泛型

1.泛型函数

func swapTwoValues<T>(inout a:T,inout b:T){
    let temporaryA = a
    a = b
    b = temporaryA
}

var someInt = 3

var anotherInt = 107

swapTwoValues(&someInt, &anotherInt)

var someString = "hello"

var anotherString = "world"

swapTwoValues(&someString, &anotherString)

2.泛型类型

struct Stack<T> {
    var items = [T]()
    mutating func push(item:T){
        items.append(item)
    }

    mutating func pop() -> T{
        return items.removeLast()
    }
}

var stackOfString = Stack<String>()

stackOfString.push("uno")

stackOfString.push("dos")

3.类型约束语法

1
2
3
4
// T 必须是SomeClass的子类,U必须遵循SomeProtocol协议
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
    // function body goes here
}

4.typealias和泛型接口

typealias为已经存在的类型重新定义名字,通过命名,可以让代码变得更便于理解。使用typealias关键字像使用普通的赋值语句一样,可以将某个已经存在的类型赋值为新的名字。

typealias Location = CGPoint

typealias Distance = Double

func distanceBetweenPoint(location:Location,toLocation:Location)->Distance{
    let dx = Distance(location.x - toLocation.x)
    let dy = Distance(location.y - toLocation.y)
    return sqrt(dx*dx+dy*dy)
}

let origin: Location = Location(x: 0, y: 0)

let point:Location = Location(x: 1, y: 1)

let distance:Distance = distanceBetweenPoint(origin, point)

typealias是单一的,必须指定将某个特定的类型通过typealias赋值为新名字,而不能将整个泛型类型进行重命名。下面这样的命名都无法通过编译。

1
2
3
4
5
6
7
class Person<T> {}

typealias Worker = Person

typealias Worker = Person<T>

typealias Worker<T> = Person<T>
一旦泛型类型的确定性得到保证后,我们就可以重命名了。

typealias Worker = Person<String>
Swift中没有泛型接口,但是使用typealias,我们可以在接口里定义一个必须实现的别名。

protocol Container {
    typealias ItemType

    mutating func append(item:ItemType)

    var count:Int{get}

    subscript(i:Int) -> ItemType{get}

}
InStack遵循Container协议。

struct IntStack:Container {
    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: ItemType) {
        self.push(item)
    }

    var count:Int{
        return items.count
    }

    subscript(i:Int) ->Int{
        return items[i]
    }
}

由于IntStack遵循Container协议的所有要求,只要通过简单的查找append方法的item参数类型和下标返回的类型,Swift就可以推断出合适的ItemType来使用,所以可以删除上面的typealias ItemTyp=Int这一行。

遵循Container协议的泛型Stack类型。

struct Stack<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]
    }
}

// 多态?????

评论