Swift 调用使用和不使用默认参数声明的函数会导致不同的结果?

Swift 调用使用和不使用默认参数声明的函数会导致不同的结果?,swift,Swift,我写这段代码是为了在操场上进行测试(学习): import Cocoa func DoIt(a: Int, b: Int, c :Int = 0) -> Int { return a + b + c; } func DoIt(a: Int, b: Int, c :NSObject) -> Int { return a * b * c.description.lengthOfBytesUsingEncoding(NSUTF8StringEncoding); } 当我使

我写这段代码是为了在操场上进行测试(学习):

import Cocoa
func DoIt(a: Int, b: Int, c :Int = 0) -> Int {
    return a + b + c;
}
func DoIt(a: Int, b: Int, c :NSObject) -> Int {
    return a * b * c.description.lengthOfBytesUsingEncoding(NSUTF8StringEncoding);
}
当我使用它时,我得到了这个:

DoIt(4, 5, 6);            // result: 20
var obj = NSObject();     // result: NSObject
DoIt(4, 5, obj);          // result: 520
我期望在执行
DoIt(4,5,6)时调用第一个函数
DoIt(Int,Int,Int)
但显然另一个正在被调用。
6
去了哪里?看起来
6
被隐式转换为
NSObject
,在objective-c中至少会发出警告。
为什么会这样

奇怪的是,如果我将最后一个
c:Int
设置为必需(通过删除
=0
),那么它将按预期工作

DoIt(4, 5, 6);            // result: 15
var obj = NSObject();     // result: NSObject
DoIt(4, 5, obj);          // result: 520

Edit1:添加了IR
如果这有助于理解发生了什么,我发出了以下命令,结果显示在gist链接中:

在Swift文件中(增加强调):

具有默认值的参数的外部名称

在大多数情况下,提供(因此需要)一个 具有默认值的任何参数的外部名称。这确保了 如果值为 在调用函数时提供

为了简化此过程,Swift提供了一个自动外部名称 用于具有默认值的任何参数。自动外置 名称与本地名称相同,就好像您编写了散列一样 代码中本地名称之前的符号

那么您的第一个函数声明

func DoIt(a: Int, b: Int, c : Int = 0) -> Int
被编译器视为

func DoIt(a: Int, b: Int, c c : Int = 0) -> Int
第三个参数的外部参数名为“c”。此函数 必须被称为

DoIt(4, 5, c: 6)   // result: 15
但是电话

DoIt(4, 5, 6)
与第一个函数的声明不匹配,仅与另一个函数的声明匹配

func DoIt(a: Int, b: Int, c :NSObject) -> Int
(第三个参数自动桥接到
NSNumber
,它是一个子类 属于
NSObject
)。这就是为什么会得到“意外”的输出

如果将第一个函数的声明更改为

func DoIt(a: Int, b: Int, _ c : Int = 0) -> Int
(其中,
表示“无外部参数名称”)
然后您将获得预期的输出:

DoIt(4, 5, 6)   // result: 15

reddit上有一条线索,也许有帮助:我不知道为什么它会这样工作,但我不相信这是故意的行为。如果是的话,我会觉得很奇怪。谢谢@SebastianDressler,我刚刚读了这篇文章。我理解隐式装箱(原语到NSNumber)及其相反的拆箱。但我不确定这里的情况是否如此。这一点尚不清楚me@nacho4d是否有可能查看生成的swift IR代码?如果是这样的话,你可以看到这里发生了什么。在这里添加生成的IR输出:这解释了很多事情!。现在我清楚地看到,对于带有optionals参数的函数,我需要使用外部参数名,或者在声明中使用
)。然而,我仍然不明白
Int
如何隐式转换为
NSObject
。@nacho4d:Swift自动将某些本机类型(Int、Float、Bool等)桥接到NSNumber,后者是NSObject的一个子类。您可以在“使用Cocoa数据类型”一节中了解更多信息我更新了答案,使之更清楚。
DoIt(4, 5, 6)   // result: 15