【Swift进阶笔记】泛型

image.png

泛型类型

可选类型是泛型

 enum Optional  {
    case none
    case some(Wrapped)
}

Array, Dictionary, Set也是泛型,如果不指定类型,系统默认为Any类型

@frozen public struct Array {
}

@frozen public struct Dictionary where Key : Hashable {
}

@frozen public struct Set where Element : Hashable {
}

var arr = ["1", 2] as [Any]

扩展类型泛型

  • 添加一个使用 Element 作为参数的便利初始化方法 (convenience initializer)
enum BinaryLeef {
    case leaf
    indirect case node(Element, l: BinaryLeef, r: BinaryLeef)
}

extension BinaryLeef {
    init(_ value: Element) {
        self = .node(value, l: .leaf, r: .leaf)
    }
}
  • 设置计算属性
extension BinaryLeef {
    var values: [Element] {
        switch self {
        case .leaf:
            return []
        case let .node(e, l, r):
            return l.values + [e] + r.values
        }
    }
}
let tree: BinaryLeef = .node(6, l: .leaf, r: .leaf)
 print(tree.values)
  • 定义泛型方法
extension BinaryLeef {
    func map(_ transform: (Element)->T) -> BinaryLeef {
        switch self {
        case .leaf:
            return .leaf
        case let .node(e, l, f):
            return .node(transform(e), l: l.map(transform), r: f.map(transform))
        }
    }
}
 let incremented: BinaryLeef = tree.map{ $0 + 1 }
 print(incremented)
  • Swift标准库常见的应用
  • Optional 用泛型参数抽象它包装的类型
  • Result 有两个泛型参数:分别表示成功和失败这两种结果对应的值的类型。
  • Unsafe[Mutable]Pointer 用泛型参数表示指针指向的对象的类型。
  • Key paths 中使用了泛型表示根类型以及路径的值类型。
  • 各种表示范围的类型,使用了泛型表达范围的上下边界

泛型和Any

Any作用相似,但是缺少类型安全性,泛型能带来编译期类型检查以及提高运行时性能等额外的好处

extension Array {
   func reduce(_ initial: Result,
   _ combine: (Result, Element) -> Result) -> Result
}

extension Array {
   func reduce(_ initial: Any, _ combine: (Any, Any) -> Any) -> Any
}

Any无法得知参数和返回值的关系,不易读

基于泛型的设计

  • 为URLSession添加一个方法
struct User: Codable {}
struct NoDataError: Error {}

extension URLSession {
    func loadUser(callBack: @escaping (Result) -> ()) {
        guard let url = URL(string: "") else { return }
        dataTask(with: url) { data, response, error in
            callBack(Result{
                if let e = error { throw e }
                guard let d = data else { throw NoDataError() }
                return try JSONDecoder().decode(User.self, from: d)
            })
        }.resume()
    }
}
  • 修改方法签名,url,解析
func load(url: URL, parse: @escaping (Data)throws->A, callBack: @escaping (Result) -> ()) {
        dataTask(with: url) { data, response, error in
            callBack(Result{
                if let e = error { throw e }
                guard let d = data else { throw NoDataError() }
                return try parse(d)
            })
        }
    }
  • 通过泛型重构去除类似代码
     URLSession.shared.loadUser {
            print($0)
     }
        
     guard let url = URL(string: "") else { return }
     URLSession.shared.load(url: url, parse: { data in
             }) {
            print($0)
      }
  • 由于URL和解析的parse函数成对出现,所以封装到同一个结构体中
struct Resource {
    let url: URL
    let parse: (Data) throws -> A
}

let profile = Resource(url: url) { data in
            try JSONDecoder().decode(User.self, from: data)
    }
  • 为了避免写重复的编码方法,添加遍历初始化方法
extension Resource where A: Codable {
    init(json url: URL) {
        self.url = url
        self.parse = { data in
            try JSONDecoder().decode(A.self, from: data)
        }
    }
}

let profile2 = Resource(json: url)

最后定义接受resource的load版本

extension URLSession {
    func load(_ resource: Resource, callBack: @escaping (Result) -> ()) {
        dataTask(with: resource.url) { data, response, error in
            callBack(Result{
                if let e = error { throw e }
                guard let d = data else { throw NoDataError() }
                return try resource.parse(d)
            })
        }
    }
}

let profile2 = Resource(json: url)
URLSession.shared.load(profile2) {
            print($0)
}

你可能感兴趣的:(【Swift进阶笔记】泛型)