2017-06-08 110 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