2016-12-07 5 views
4

Играя с кодом образца из Swift Language Guide: Extensions я extedned структуры Удвоение как этогонеявного типа литье в Swift

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

Я был удивлен, что это заявление

2.someFunc() 

не генерировал ошибку компиляции времени, как : Значение типа 'Int' не имеет члена 'someFunc'. Я ожидал, что значение 2 будет неявным образом занесено в Int, но Swift выдаст его в Double. Почему это ? Как Swift определяет, что значение 2 в этом случае имеет тип Double?

Тогда я попытался назвать SomeFunc(), как этот

let x = 2 
x.someFunc() 

Здесь я получаю ожидаемое время ошибки

компиляции Does'n этом противоречат заявление в Swift Programming Language 3.0.1 : Language guide : The basics : Type Safety and Type Inference?

Тип вывода позволяет компилятору автоматически вывести тип конкретного выражения при компиляции кода, просто исследуя значения, которые вы предоставляете.

EDIT

Из ответов я узнал, что это происходит потому, что двойной соответствует протоколу ExpressibleByIntegerLiteral. Однако структура Float также соответствует ей и некоторым другим типам. Ниже я создал свою структуру, которая также соответствует этому протоколу. В конце концов, Double выбирается во время компиляции. Зачем? Каким образом приоритет метода от одного расширения определяется по методу из другого расширения?

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

Это хороший вопрос в редактировании. – Alexander

ответ

3

Двойник один из типов, который соответствует протоколу ExpressibleByIntegerLiteral. Поскольку 2 является целочисленным leteral, компилятор может проверить, какой из типов, соответствующих протоколу, имеет someFunc(), и поскольку только Double делает, в этом контексте нет никакой непостоянства.

+1

Float struct также соответствует этому протоколу, но не компилируется. расширение Float { функ SomeFunc() { печать ("всплывают SomeFunc") }} 4.someFunc() ли это все, что нужно? И что, если бы я расширил две структуры с помощью someFunc() - как я узнаю, какой из них будет выбран во время выполнения? – Radek

+1

Я думаю, что это связано с этим: «Swift всегда выбирает Double (а не Float) при выводе типа чисел с плавающей запятой» https://developer.apple.com/library/content/documentation/Swift/Conceptual/ Swift_Programming_Language/TheBasics.html –

2

Double соответствует ExpressibleByIntegerLiteral. В вашем примере компилятор видит, что из всех типов, которые соответствуют ExpressibleByIntegerLiteral, только Double содержит someFunc(), поэтому он знает, что нужно создать Double из 2.

Как вы заметили в своем втором примере, это поведение не определяет неявное литье между типами. Это относится только к литералам.