2017-10-10 1 views
1

Exemple:Impossible de convertir la valeur de type '(T) -> Void'

struct Wrapper<T> { 
    var key: Int = 0 
    var listeners: [Int: (T) -> Void] = Dictionary() 

    mutating func add(_ handler:@escaping (T) -> Void) { 
     self.key += 1 
     self.listeners[self.key] = handler 
    } 

    func get(key: Int) -> (T) -> Void { 
     return self.listeners[key]! 
    } 
} 

Protocole d'essai:

protocol CommonProtocol { 

} 

classe qui créent Wrapper de classe de test

class C { 
    var wrapper: Wrapper = Wrapper<CommonProtocol>() 

    func add<T: CommonProtocol>(_ handler: @escaping (T) -> Void) { 
     self.wrapper.add(handler) //Cannot convert value of type '(T) -> Void' to expected argument type '(CommonProtocol) -> Void' 
    } 
} 

Image with error

Je reçois Erreur:

Cannot convert value of type '(T) -> Void' to expected argument type '(CommonProtocol) -> Void' 

Question:

Why (T) -> Void can't be casted to (CommonProtocol) -> Void ? The T is explicitly declared as <T: CommonProtocol>

Ceci est ma première question, si vous avez des suggestions s'il vous plaît ne pas hésiter à me contacter

+1

Le compilateur est tout à fait correct. a '(T) -> Void' n'est pas un' (CommonProtocol) -> Void'. Disons 'String: CommonProtocol' et' Int: CommonProtocol'. Substituer 'String' pour' T'. Si '(T) -> Void' était convertible en' (CommonProtocol) -> Void', on pourrait alors passer un 'Int' dans un paramètre' String'. – Hamish

+0

@Hamish, Vous avez raison, mais si je change la fonction 'ajouter' à ceci:' func add (_ handler: @escaping (CommonProtocol) -> Void) 'Je ne reçois aucune erreur, il semble que le problème soit ce que vous disons, cela doit aussi être une erreur – oxview

+0

Pourquoi vous attendez-vous à ce que ce soit une erreur? Vous passez maintenant un '(CommonProtocol) -> Void' à quelque chose qui attend un' (CommonProtocol) -> Void' - c'est tout à fait légal. – Hamish

Répondre

0

Vous n'avez pas besoin de faire func add générique. Lorsque vous spécifiez dans func add<T: CommonProtocol>... vous explicitement dire au compilateur que votre fonction accepte tous les types qui héritentCommonProtocol mais votre Wrapper spécifie qui accepte CommonProtocol types non hérités.

Solution

Chaque type effaçable classe C:

Class C<T: CommonProtocol> { 
    var wrapper: Wrapper<T> 
    .... 
} 

ou si le type T n'importe pas vraiment à vous alors:

func add(_ handler: @escaping (CommonProtocol) -> Void) 

mais second ne fait pas sens du tout. Vous devez le baisser chaque fois que vous utiliserez cette méthode (et les downcasts sont très mauvais: D)

Note: Ce n'est pas vraiment lié à cette question, mais une de vos options est de taper CommonProtocol aussi .