2017-06-08 4 views
3

J'ai rencontré un problème lors de la migration de la base de code Swift 3.1 vers Swift 4.Swift 4: Implémentation d'un protocole générique avec protocole en tant que type associé

Le problème se pose lorsque vous essayez d'implémenter une méthode de protocole générique qui prend comme paramètre un paramètre de fermeture avec un paramètre générique associé à un protocole. Il est plus facile qu'il n'y paraît :)

Le code suivant fonctionne très bien à 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) {  
    } 
} 

Cependant Swift 4 compilateur me donne une erreur au sujet de la classe Foo non conforme au protocole FooType avec foo(action:) implémentation de la méthode manquante. Par ailleurs, Xcode 9 "fix-it" génère la même implémentation que je l'ai fait.

Le code se compile si j'utilise BarType comme type de paramètre, mais il n'est pas bon de perdre des informations de type concret.

Répondre

3

Transforme que la suppression de la ligne

typealias BarType = Bar 

résout le problème. Ce qui est juste - l'inférence de type fait son travail. Néanmoins, ce devrait être un code légal et cela ressemble à un bogue dans le compilateur.

Reported en conséquence.

0

Nous devrions utiliser la variable générique typealias pour fournir le type à associatedType du protocole. Je voudrais utiliser le nom de variable générique typealias dans funtion. Cela a plus de sens et est légal mais je ne sais toujours pas pourquoi le compilateur ne connaît pas le paramètre typealias en fermeture.

class Foo: FooType { 
    typealias BarType = Bar 


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


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

C'est légal. Cependant, nous perdons de la clarté dans le code sur le type concret avec lequel nous travaillons dans cette implémentation. L'inférence de type nous aide même en ne forçant pas une déclaration 'typealias' si l'implémentation de toutes les exigences du protocole fournit le type concret avec lequel elle travaille. Vous pouvez consulter [Explication Apple] (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html) dans la section Types associés. – chezzdev