2016-12-07 1 views
4

Jouer avec l'exemple de code de Swift Language Guide: Extensions J'ai extedned Double struct comme cecoulée de type Implicite dans Swift

extension Double { 
    func someFunc() { 
     print("someFunc") 
    } 
} 

J'ai été surpris que cette déclaration

2.someFunc() 

n'a pas généré erreur de compilation de temps comme : La valeur du type 'Int' n'a aucun membre 'someFunc'. Je m'attendais à ce que la valeur de 2 soit implicitement castée à Int, mais Swift la jeta à Double. Pourquoi donc ? Comment Swift détermine-t-il que la valeur de 2 dans ce cas est de type Double?

J'ai essayé d'appeler someFunc() comme

let x = 2 
x.someFunc() 

Ici j'obtiens l'erreur de compilation attendue

Does'n cette déclaration en contradiction avec Swift Programming Language 3.0.1 : Language guide : The basics : Type Safety and Type Inference?

inférence de type permet un compilateur de déduire le type d'une expression particulière automatiquement lorsqu'il compile votre code, simplement en examinant les valeurs que vous fournissez.

EDIT

D'après les réponses que j'ai appris que cela arrive parce que Double est conforme au protocole ExpressibleByIntegerLiteral. Cependant Float struct s'y conforme aussi et d'autres types aussi. Ci-dessous j'ai créé ma structure qui est également conforme à ce protocole. À la fin, cependant, Double est choisi au moment de la compilation. Pourquoi? Comment la préséance de la méthode d'une extension est-elle déterminée par rapport à la méthode d'une autre extension?

struct someStruct: ExpressibleByIntegerLiteral{ 
    var i:Int = 0 

    init(integerLiteral value: Int64){ 
     i = Int(value) 
    }  
} 

extension someStruct { 
    func someFunc() {print("Somestruct someFunc") } 
} 

extension Double { 
    func someFunc() { print("Double someFunc") } 
} 

4.someFunc() 

//prints: Double someFunc 
+0

C'est une bonne question dans le montage. – Alexander

Répondre

3

double est l'un des types qui se conforme au protocole ExpressibleByIntegerLiteral. Puisque 2 est un entier leteral, le compilateur peut vérifier lequel des types conformes au protocole a une fonction someFunc() et comme seul Double le fait, il n'y a pas d'ambiguïté dans ce contexte.

+1

Float struct est également conforme à ce protocole mais il ne compile pas. l'extension flotteur { func someFunc() { print ("flotter someFunc") }} 4.someFunc() Est-ce tout ce qui est nécessaire? Et si j'avais étendu deux structures avec cette fonction someFunc() - comment puis-je savoir lequel sera choisi lors de l'exécution? – Radek

+1

Je pense que cela a à voir avec ceci: "Swift choisit toujours Double (plutôt que Float) pour inférer le type de nombres à virgule flottante" https://developer.apple.com/library/content/documentation/Swift/Conceptual/ Swift_Programming_Language/TheBasics.html –

2

Double est conforme à ExpressibleByIntegerLiteral. Dans votre exemple, le compilateur voit que de tous les types qui se conforment à ExpressibleByIntegerLiteral, seul Double contient someFunc(), donc il sait créer un Double sur 2.

Comme vous l'avez remarqué dans votre deuxième exemple, ce comportement ne définit pas la conversion implicite entre types. Cela ne s'applique qu'aux littéraux.