2017-06-12 6 views
0

J'écrivais un exemple de code dans un terrain de jeu et je voulais une fonction qui renvoie la distance entre deux valeurs, qui sont toutes deux conformes au protocole Strideable dans Swift afin que je puisse utiliser le distance(to other: Self) -> Self.Stride fonction. Ma mise en œuvre se résume comme suit:Générique Où ambiguïté de la clause avec les types associés dans Swift

func distanceFrom<T: Strideable, U>(_ a: T, to b: T) -> U where T.Stride == U 
{ 
    return a.distance(to: b) 
} 

Après avoir observé cette fonction pendant un certain temps, je me suis aperçu que je ne savais pas que Stride était utilisé dans la clause where, celle de a ou de b. D'après ce que je comprends, il serait possible pour a et b de définir différents types associés pour Stride. Aussi, je n'ai fait aucune déclaration pour m'assurer que a.Stride == b.Stride, bien que je comprenne que je pourrais développer ma clause where pour le faire.

Alors, lequel serait utilisé pour vérifier l'équivalence à U? Pour être clair, la question ne concerne pas ce bloc de code particulier, mais plutôt toute situation dans laquelle cette ambiguïté existerait.

Répondre

1

a et b sont du même type. Si vous les vouliez être différents types Strideable vous devez ajouter un autre paramètre générique conforme à Strideable telle que la signature de la fonction se présente comme suit:

func bar<T: Strideable, V: Strideable, U>(_ a: T, to b: V) -> U where T.Stride == U, V.Stride == U { 
    return a.distance(to: a) //Trivial return statement (see explanation below) 
} 

Bien que le code mentionné ci-dessus compilerait, return a.distance(to: b) ne compilerait pas parce qu'ils (a et b) sont différents types et la définition de distance dans Swift3 est public func distance(to other: Self) -> Self.Stride (notez l'utilisation de Self qui limite other au même type que le Strideable sur lequel cette fonction est appelée). En conclusion, bien que vous puissiez faire a et b différents types, pour votre application cela n'aurait pas de sens de le faire.

Comme preuve supplémentaire pour ne pas être en mesure d'appeler votre code posté original avec différents types s'il vous plaît voir le joint Playground screenshot qui montre une erreur lors de l'utilisation de différents types.

Cependant, cela fonctionne très bien dans la cour de récréation.

func distanceFrom<T: Strideable, U>(_ a: T, to b: T) -> U where T.Stride == U { 
    return a.distance(to: b) 
} 


let doubleFoo: Double = 4.5 
let intFoo: Double = 4 

let g = distanceFrom(doubleFoo, to: intFoo) // gives me a double of -0.5 

J'espère que cela aide.

+0

Je crois que a et b seraient tous deux conformes au protocole Strideable, mais ils pourraient être de types différents. J'ai testé l'appel de cette fonction avec un être un Int et b étant un Double et il compile et fonctionne comme prévu. – tnev

+0

Veuillez réessayer en utilisant la capture d'écran et l'extrait de code que j'ai ajouté à ma réponse. Je crois qu'ils (les deux T) doivent être du même type. – Underhill