【问题标题】:Swift 4: Implementation of a generic protocol with protocol as an associated typeSwift 4:以协议作为关联类型的通用协议的实现
【发布时间】:2017-06-08 18:10:30
【问题描述】:

我在从 Swift 3.1 到 Swift 4 代码库迁移期间遇到了问题。

当您尝试实现一个泛型协议方法时,就会出现问题,该方法采用带有泛型参数的闭包,并将协议作为关联类型。这比听起来容易:)

以下代码在 Swift 3.1 中运行良好:

protocol FooType {
    associatedtype BarType

    func foo(bar: BarType)
    func foo(action: (BarType) -> Void)
}

protocol Bar {}

class Foo: FooType {
    typealias BarType = Bar

    // Compiles in both 3.1 and 4
    func foo(bar: Bar) {
    }

    // ERROR: Candidate has non-matching type (Bar) -> Void
    func foo(action: (Bar) -> Void) {     
    }
}

然而,在 Swift 4 编译器中,我给出了一个关于类 Foo 不符合协议 FooType 且缺少 foo(action:) 方法实现的错误。

顺便说一句,Xcode 9 “修复”生成的实现与我的实现相同。

如果我使用BarType 作为参数类型,代码可以编译,但丢失具体类型信息并不好。

【问题讨论】:

    标签: swift generics type-inference xcode9-beta swift4


    【解决方案1】:

    原来删除线

    typealias BarType = Bar
    

    解决了这个问题。这是公平的 - 类型推理完成了它的工作。

    尽管如此,它应该是合法的代码,并且看起来像是编译器中的一个错误。

    Reported 相应地。

    【讨论】:

      【解决方案2】:

      我们应该使用 typealias 泛型变量将类型提供给 协议的关联类型。我会在函数中使用 typealias 通用变量名。这更有意义和合法,但我仍然不知道为什么编译器不知道闭包中的 typealias 参数。

      class Foo: FooType {
          typealias BarType = Bar
      
      
          func foo(bar: BarType) {
           /*Code*/
          }
      
      
          func foo(action: (BarType) -> Void) {
            /*Code*/
          }
      }
      

      【讨论】:

      • 这是合法的。然而,我们在代码中失去了关于我们在这个实现中使用的具体类型的清晰度。如果所有协议要求的实现都提供了它正在使用的具体类型,则类型推断甚至可以通过不强制声明 typealias 来帮助我们。您可以在关联类型部分查看Apple explanation
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多