Swift 4:将协议作为关联类型

时间:2017-06-08 18:10:31

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

我在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“fix-it”会产生与我相同的实现。

如果我使用BarType作为参数类型,代码会编译,但是松散具体类型信息并不好。

2 个答案:

答案 0 :(得分:3)

原来是删除了行

typealias BarType = Bar

解决了这个问题。哪种是公平型推理能够完成它的工作。

然而,它应该是一个合法的代码,似乎是编译器中的一个错误。

相应地

Reported

答案 1 :(得分:0)

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

class Foo: FooType {
    typealias BarType = Bar


    func foo(bar: BarType) {
     /*Code*/
    }


    func foo(action: (BarType) -> Void) {
      /*Code*/
    }
}