在Swift中的隐式类型转换

5

在使用Swift编程语言指南:扩展中的示例代码后,我将结构体Double进行了扩展,如下所示:

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

我很惊讶这个声明。
2.someFunc()

没有生成编译时错误,例如:类型“Int”没有成员“someFunc”。我预期值为2会被隐式转换为Int,但Swift将其转换为Double。为什么?Swift如何确定这种情况下的值2的类型是Double?
然后我尝试像这样调用someFunc()
let x = 2
x.someFunc()

这里我得到了预期的编译时错误。

这是否与Swift 3.0.1 编程语言指南: 基础知识: 类型安全和类型推断中的说法相矛盾呢?

类型推断允许编译器自动推导出编译代码时特定表达式的类型,只需检查您提供的值即可。

编辑

从回复中我了解到这是因为Double符合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

在编辑中,那是一个很好的问题。 - Alexander
2个回答

3

Double是符合协议ExpressibleByIntegerLiteral的类型之一。由于2是一个整数字面量,编译器可以检查哪些符合协议的类型具有someFunc(),而只有Double具有该函数,在此上下文中没有歧义。


1
浮点数结构体也符合此协议,但它无法编译。 扩展浮点数结构体: extension Float { func someFunc() { print("float someFunc") } }4.someFunc() 这就是所需的全部吗?如果我用someFunc()扩展了两个结构体,那么如何知道在执行时选择哪一个? - Radek
1
我认为这与以下内容有关:“在推断浮点数类型时,Swift 总是选择 Double(而不是 Float)”。https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html - Josh Homann

2

Double符合ExpressibleByIntegerLiteral。在您的示例中,编译器看到符合ExpressibleByIntegerLiteral的所有类型中,只有Double包含someFunc(),因此它知道要从2创建一个Double

正如您在第二个示例中注意到的那样,这种行为不定义类型之间的隐式转换。它仅适用于字面量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接