【问题标题】:Swift extension type constraints for generic class where generic type is yet another generic type泛型类的 Swift 扩展类型约束,其中泛型类型是另一种泛型类型
【发布时间】:2019-11-21 14:43:55
【问题描述】:

我正试图围绕 Swift 中的泛型类型约束。这是我的出发点:

class Promise<T> {
    func resolve(_ block:@escaping (T) ->Void) {}
    func fulfill(_ result:T) {}
}

承诺就是这样,可以在未来实现。当它与 Swift 的 Result 类型一起使用时,当将结果从后台队列返回到主队列时,这将变得非常有用:

let promise = Promise<Result<String, Error>>()
promise.fulfill(.success("Hello"))
promise.fulfill(.failure(NSError()))

现在我想为所有使用Result 添加这些辅助方法的 Promise 实例添加一个扩展:

extension Promise where T == Result<X, Error> {
                                    ⬆︎ Here's the problem ⚡️
    func failure(_ error:Error) {
        fulfill(.failure(error))
    }

    func success(_ result:X) {
        fulfill(.success(result))
    }
}

// Shorter:
let promise = Promise<Result<String, Error>>()
promise.success("Hello")
promise.failure(NSError())

唯一的问题是上面的代码没有编译,因为X没有定义。我想表达的是:

T的泛型类型为Result&lt;X,Z&gt;时扩展Promise,其中X可以是任何类型,Z必须是Error类型→Result&lt;*, Error&gt;。这可能吗?

【问题讨论】:

    标签: swift generics swift-extensions type-constraints


    【解决方案1】:

    你想要的都是可能的,只是语法有点冗长。您不能将 where 约束放在扩展上。你必须把它放在每个方法上。

    extension Promise {
    
        func failure<U>(_ error: Error) where T == Result<U, Error> {
            fulfill(.failure(error))
        }
    
        func success<U>(_ result: U) where T == Result<U, Error> {
            fulfill(.success(result))
        }
    }
    

    您也可以使用协议来实现,但是对于枚举,我觉得这很笨拙,因为不能将枚举案例视为符合方法。

    protocol ResultType {
        associatedtype Success
        associatedtype Failure: Error
        static func makeFailure(_: Failure) -> Self
        static func makeSuccess(_: Success) -> Self
    }
    
    extension Result: ResultType {
        static func makeFailure(_ failure: Failure) -> Result<Success, Failure> { .failure(failure)  }
        static func makeSuccess(_ success: Success) -> Result<Success, Failure> { .success(success) }
    }
    
    extension Promise where T: ResultType {
        func failure(_ error: T.Failure) {
            fulfill(T.makeFailure(error))
        }
    
        func success(_ result: T.Success) {
            fulfill(T.makeSuccess(result))
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多