美文网首页Swift基础
【Swift进阶笔记】泛型

【Swift进阶笔记】泛型

作者: BeethOven | 来源:发表于2022-03-02 18:47 被阅读0次
image.png

泛型类型

可选类型是泛型

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

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

@frozen public struct Array<Element> {
}

@frozen public struct Dictionary<Key, Value> where Key : Hashable {
}

@frozen public struct Set<Element> where Element : Hashable {
}

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

扩展类型泛型

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

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

泛型和Any

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

extension Array {
   func reduce<Result>(_ 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<User, Error>) -> ()) {
        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<A>(url: URL, parse: @escaping (Data)throws->A, callBack: @escaping (Result<A, Error>) -> ()) {
        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<A> {
    let url: URL
    let parse: (Data) throws -> A
}

let profile = Resource<User>(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<User>(json: url)

最后定义接受resource的load版本

extension URLSession {
    func load<A>(_ resource: Resource<A>, callBack: @escaping (Result<A, Error>) -> ()) {
        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<User>(json: url)
URLSession.shared.load(profile2) {
            print($0)
}

相关文章

  • 【Swift进阶笔记】泛型

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

  • Swift进阶 :泛型

    swift 进阶之路:学习大纲[https://www.jianshu.com/p/115367c3eefd] 本...

  • Swift进阶-泛型

    为什么会有泛型? 我们发现, multiNumInt(::) 、 multiNumDouble(::) 函数体是...

  • 《Swift从入门到精通》(十九):泛型

    泛型(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 泛型可解决的问题如两个 Int 类型交...

  • Swift进阶之泛型

    泛型Generic在swift中非常重要,它提升了代码的通用性和简洁性,很多开源的组件都是通过泛型来实现。泛型是什...

  • Swift进阶(十三)泛型

    泛型(Generics) 泛型可以将类型参数化,提高代码复用率,减少代码量下面我们来看一个经典的例子,a b交换,...

  • Swift-进阶:泛型

    本文主要介绍泛型及其底层原理 泛型 泛型主要用于解决代码的抽象能力 + 代码的复用性 例如下面的例子,其中的T就是...

  • Swift进阶十一:泛型

    一:重载 重载和泛型紧密相关.拥有同样名字,但是参数或返回类型不同的多个方法互相称为重载方法,方法的重载并不意味着...

  • Swift-泛型笔记

    Swift 泛型 Swift 提供了泛型让你写出灵活且可重用的函数和类型。 Swift 标准库是通过泛型代码构建出...

  • [ WWDC2018 ] - Swift 泛型 Swift Ge

    Swift 泛型历史 我们首先来回顾一下 Swift 中对于泛型支持的历史变更,看看现在在 Swift 中,泛型都...

网友评论

    本文标题:【Swift进阶笔记】泛型

    本文链接:https://www.haomeiwen.com/subject/julerrtx.html