Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 818
Radek Avatar asked Dec 07 '16 08:12

Radek


People also ask

What is type casting in Swift?

Type casting is a way to check the type of an instance, or to treat that instance as a different superclass or subclass from somewhere else in its own class hierarchy. Type casting in Swift is implemented with the is and as operators.

How do I cast an any value to any in Swift?

The Any type represents values of any type, including optional types. Swift gives you a warning if you use an optional value where a value of type Any is expected. If you really do need to use an optional value as an Any value, you can use the as operator to explicitly cast the optional to Any, as shown below. let optionalNumber: Int? = 3

What is the use of is in Swift?

It is used to check whether the instance type belongs to a particular super class or subclass or it is defined in its own hierarchy. Swift 4 type casting provides two operators 'is' to check the type of a value and 'as' and to cast the type value to a different type.

What are any and anyobject in Swift?

Type Casting for Any and AnyObject¶. Swift provides two special types for working with nonspecific types: Any can represent an instance of any type at all, including function types. AnyObject can represent an instance of any class type.


2 Answers

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.

like image 125
Josh Homann Avatar answered Oct 26 '22 13:10

Josh Homann


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.

like image 29
Alexander Avatar answered Oct 26 '22 15:10

Alexander