Swift学习笔记22——泛型(Generics)

泛型函数

当我们写一个函数的时候,一般都会指明参数的类型。比如下面两个实现交换变量的函数(摘自官方文档)

func swapTwoInts(inout a: Int, inout _ b: Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
上面的只是限于交换整形。但是如果我们相对Double或Float类型,甚至是任何类型的数据实现交换的功能,我们都要分别写一个函数。这是无比麻烦的。

所以有了泛型这个概念,泛型就是模糊的类型。当我们函数的功能实现和具体类型没关系的时候,就可以使用泛型。
有了泛型,我们可以将上面实现两个变量交换的功能用一个方法完成,这个方法可以用于不同的数据类型

func swapTwoValues<T>(inout a: T, inout _ b: T) {
    let temporaryA = a
    a = b
    b = temporaryA
}
主要的语法就是上面的<T>,这个T就是代表某个类型,但是没有指明具体是哪种类型。而且这个T,可以换成你希望的标示符,只要不是关键字。并且一般要求单词的首字母要大写,比如Element、Value等。而且能指定多个类型,见下面的类型约束

泛型的函数调用方法和普通函数是一样的。下面创建了两个Animal实例,然后使用刚刚定义的函数交换数据。

var cat = Animal()
cat.life = 1
var dog = Animal()
dog.life = 2

swapTwoValues(&cat, &dog)
print(cat.life)  // 2
print(dog.life)  // 1

泛型类型

定义一个类型,但是它可以对不同类型的数据进行操作。比如Array和Dictionary这两个集合结构体,他们可以装不同类型的数据,这就是泛型类型。

官方文档给我们展示了一个泛型类型的栈,它使用Array来实现.

struct Stack<Element> {
    var items = [Element]()
    mutating func push(item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

然后在创建这种泛型类型实例的时候,我们必须指定所属的类型。

var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")

泛型约束

我们可以对泛型进行约束,让他们必须遵守某些协议,官方文档语法如下

func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
    // function body goes here
}

同时还可以添加where约束符再对泛型进行限制

func someFunction<T: SomeClass, U: SomeProtocol where T.someItem == U, U.someItem: SomeClass2>(someT: T, someU: U) {
    // function body goes here
}


关联类型

在定义协议的时候,我们可能需要定义一个或多个类型作为我们协议的一部分。而这些类型是不确定的,只有到具体的类实现协议的时候才能确定,这个时候我们可以使用关联类型来实现。所谓的关联类型就是一个占位符,等到具体实现协议的时候才知道它具体是什么类型。官方例子如下:

protocol Container {
    typealias ItemType
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

然后在实现协议的时候,我们可以指定ItemType具体是什么类型

struct IntStack: Container {
    // original IntStack implementation
    var items = [Int]()
    mutating func push(item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
    // conformance to the Container protocol
    typealias ItemType = Int
    mutating func append(item: Int) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Int {
        return items[i]
    }
}

同时又因为有Swift的类型判断机制,所以我们在实现了协议的其他方法之后,编译器会自动判断关联类型是什么,不需要我们显式地指定。所以上面代码指定关联类型为Int的那行可以删去。


泛型OC是不支持的,但是java支持。使用泛型能给编程带来很大的便利。


引用文档

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html#//apple_ref/doc/uid/TP40014097-CH26-ID179



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值