Radek
Radek

Reputation: 621

Implicit type casting in Swift

Playing with the sample code from Swift Language Guide: Extensions I've extedned struct Double like this

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

I was surprised that this statement

2.someFunc()

did not generate compile time error like: Value of type 'Int' has no member 'someFunc'. I've expected value of 2 to be implicitly casted to Int but Swift casted it to Double. Why is that ? How does Swift determine that value of 2 in this case is of type Double ?

Then I've tried calling someFunc() like that

let x = 2
x.someFunc()

Here I get the expected compile time error

Does'n this contradict statement in Swift Programming Language 3.0.1 : Language guide : The basics : Type Safety and Type Inference?

Type inference enables a compiler to deduce the type of a particular expression automatically when it compiles your code, simply by examining the values you provide.

EDIT

From the responses I've learned that it happens because Double conforms to ExpressibleByIntegerLiteral protocol. However Float struct also does conform to it and some other types as well. Below I have created my struct that also conforms to that protocol. In the end however Double is chosen at compile time. Why? How is the precedence of method from one extension determined over the method from other 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

Upvotes: 5

Views: 1023

Answers (2)

Alexander
Alexander

Reputation: 63271

Double conforms to ExpressibleByIntegerLiteral. In your example, the compiler sees that of the all the types that conform to ExpressibleByIntegerLiteral, only Double contains someFunc(), so it knows to create a Double out of 2.

As you noticed in your second example, this behaviour doesn't define implicit casting between types. It only applies to literals.

Upvotes: 2

Josh Homann
Josh Homann

Reputation: 16327

Double is one of the types that conforms to the protocol ExpressibleByIntegerLiteral. Since 2 is an integer leteral, the compiler can check which of the types conforming to the protocol has a someFunc() and since only Double does, there is no abiguity in this context.

Upvotes: 3

Related Questions