木又的《Swift进阶》读书笔记——泛型

207 阅读3分钟

泛型

  • 泛型编程是一种可以保持类型安全性的代码重用技术。

  • 可以认为泛型是 **多态 (polymoyphism) ** 的一种形式,而多态则是指一个接口或名称可以通过多个类型进行访问的现象。

    至少有四种不同的概念,可以归纳到 多态编程 这个范畴里:

    • 可以定义多个同名但是类型不同的方法。这种用法叫做 重载(overloading),或者更技术地说,这是一种 专属多态 (ad hod polymorphism)
    • 当一个函数或方法接受类 C 作为参数的时候,我们也可以给它传递 C 的派生类,这种用法叫做 子类型多态 (subtype polymorphism)
    • 当一个函数 (通过尖括号语法) 接受泛型参数的时候,我们管这个函数叫做 泛型函数 (generic function),类似地,还有泛型类型和泛型方法。这种用法叫做 参数化多态 (parametric polymorphism)。这些泛型化的参数,叫做 泛型 (generics)
    • 我们可以定义一个协议并让多个类型实现它。这是另外一种更加结构化的 专属多态

泛型类型

  • 恒等函数 (identify function)

    func identity<A>(_ value: A) -> A {
      return value
    }
    
  • Optional 的定义

    enum Optional<Wrapped> {
      case none
      case some(Wrapped)
    }
    

    可以把 Optional 当作一个 类型构建器 (type constructor):给它传递一个具体类型 (例如:Int),它就会创建一个新的具体类型 (例如:Optional<Int>)。

扩展泛型类型

在 Swift 里,很多集合类型都是泛型类型 (例如: Array, Set 和 Dictionary)。但是,泛型这项技术本身可不仅仅用在表达集合类型上。它的应用几乎贯穿了整个 Swift 标准库的实现,例如:

  • Optional 用泛型参数抽象它包装的类型。
  • Result 有两个泛型参数:分别表示成功和失败这两种结果对应的值的类型。
  • Unsafe[Mutable]Pointer 用泛型参数表示指针指向的对象的类型。
  • Key paths 中使用了泛型表示根类型以及路径的值类型。
  • 各种表示范围的类型,使用了泛型表达范围的上下边界。

泛型和 Any

通常,泛型和 Any 的用途是类似的,但它们有截然不同的表现。在没有泛型的编程语言里,Any 通常用来实现和泛型同样的效果,但是却缺少了类型安全性。这通常意味着要使用一些运行时特性,例如内省 (introspection) 或动态类型转换,把 Any 这种不确定的类型变成一个确定的具体类型。而泛型不仅能解决绝大部分同样的问题,还能带来编译期类型检查以及提高运行时性能等额外的好处。

基于泛型的设计

泛型在程序设计之初就可以派上用场,它们可以在众多类型中剥离出共享的罗及并生成模板代码。

extension URLSession {
  func load<A>(_ r: Resource<A>,
              callback: @escaping (Result<A, Error>) -> ()) {
  	dataTask(with: r.url) { data, response, err in
                          callback(Result {
                          	if let e = err { throw e }
                            guard let d = data else { throw NoDataError() }
                            return try.r.parse(d)
                          })
                         }.resume()
  }
}

现在,我们就能用表示用户信息的资源调用 load,并且在回调函数里,得到一个 User 对象或者一个错误了:

URLSession.shared.load(profile) { result in
	print(result)                                
}