【问题标题】:Declaring a return value of enum containing a case with a generic type?声明包含泛型案例的枚举的返回值?
【发布时间】:2018-01-23 18:48:42
【问题描述】:

我有一个简单的网络结果枚举。如果调用成功,我将使用请求类型的对象返回成功。如果不成功,我会返回失败信息。

enum Result<T> {
    case success(T)
    case failure(String)
}

func testAPI(requestedObjClass: String) -> Result {...}

使用此代码,编译器会给出错误:

Reference to generic type 'Result' requires arguments in <...>

它希望我用Result&lt;MyObj&gt; 之类的东西定义“成功”案例的类型,但根据参数的不同,它可能是不同的类型,我什至可能根本不会返回成功。这个“结果”想法的正确架构是什么?

【问题讨论】:

    标签: swift enums


    【解决方案1】:

    编译器需要在编译时解析泛型类型占位符值。例如,在

    if case .success(let res) = testAPI(requestedObjClass: "...") {
        print(res)
    }
    

    编译器需要知道res 的类型。因此你不能 返回一个 Result,其中对应的 T 仅在运行时确定。

    可能的解决方案是将请求的结果类型作为 一个类型而不是一个字符串,并使函数泛型:

    func testAPI<T>(requestedObjClass: T.Type) -> Result<T> {
        // ...
    }
    

    然后在像这样的电话中

    if case .success(let res) = testAPI(requestedObjClass: Int.self) {
        print(res)
    }
    

    编译器可以推断出类型T(从而推断出结果的类型 编译时的值res),在本例中为Int

    【讨论】:

    • 你也许可以完全删除requestedObjClass,但我不确定Swift编译器是否足够聪明,可以从if case.success(let res: Int) = testAPI() {推断类型
    • @Samah:类型可以从上下文中推断出来,例如在let res: Result&lt;Int&gt; = testAPI() 中,但if case success(let res as Int) = testAPI() 无法编译。我还是更喜欢let res = testAPI(Int.self)
    【解决方案2】:

    它希望我用一些东西来定义“成功”案例的类型 像结果,但它可能是不同的类型,具体取决于 论据

    您可以编写一些协议,例如 MyProtocol,然后使用此协议扩展 MyObj 和所有其他需要的类,例如

    class MyObj { }
    
    protocol MyProtocol { }
    
    extension MyObj: MyProtocol { }
    
    extension Int: MyProtocol { }
    
    enum Result<T> {
        case success(T)
        case failure(String)
    }
    
    func testAPI(requestedObjClass: String) -> Result<MyProtocol> {
        return .failure("Not implemented")
    }
    

    一般来说,为MyProtocol 形成一些约束是个好主意,比如方法或计算变量。拥有过于动态的东西不是很快速的方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多