Reputation: 621
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
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
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