2017-06-08 112 views
3

在Swift 3.1到Swift 4代码库迁移过程中,我遇到了一个问题。Swift 4:使用协议作为关联类型实现通用协议

当您尝试实现一个通用协议方法,该协议方法将带有通用参数的闭包与协议作为关联类型相结合时,问题就会出现。它更容易比它的声音:)

下面的代码在雨燕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) {  
    } 
} 

但是在斯威夫特4编译器给了我有关类Foo不符合协议FooTypefoo(action:)方法实现丢失的错误。

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

如果我使用BarType作为参数类型,代码将会编译,但不适用于删除具体类型信息。

回答

3

原来,除去线

typealias BarType = Bar 

解决问题。这是公平的 - 类推断做它的工作。

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

Reported相应地。

0

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

class Foo: FooType { 
    typealias BarType = Bar 


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


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

这是合法的。但是,我们正在放弃关于在这个实现中与我们合作的具体类型的代码的清晰度。如果所有协议要求的实现提供了它正在使用的具体类型,类型推断甚至可以帮助我们不强制使用'typealias'声明。 您可以在相关类型部分查看它的[Apple解释](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html)。 – chezzdev