使用和不使用默认参数声明的调用函数会导致不同的结果?
calling function declared with and without default parameter leads to different results?
我在操场上为了测试(学习)目的编写了这段代码:
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
如果这有助于理解发生了什么,我发出了以下命令,结果在要点 link 中:https://gist.github.com/nacho4d/94fdb72d8a3fee0c09e5
$ swiftc \
-emit-ir /Users/nacho4d/Desktop/function2/function2/main.swift \
-sdk Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk
来自 Swift 文档中的 "Functions"(强调已添加):
External Names for Parameters with Default Values
In most cases, it is useful to provide (and therefore require) an
external name for any parameter with a default value. This ensures
that the argument for that parameter is clear in purpose if a value is
provided when the function is called.
To make this process easier, Swift provides an automatic external name
for any parameter that has a default value. The automatic external
name is the same as the local name, as if you had written a hash
symbol before the local name in your code.
所以你的第一个函数声明
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
)。这就是你得到 "unexpected" 输出的原因。
如果将第一个函数的声明改为
func DoIt(a: Int, b: Int, _ c : Int = 0) -> Int
(其中 _
代表 "no external parameter name")
然后你会得到预期的输出:
DoIt(4, 5, 6) // result: 15
我在操场上为了测试(学习)目的编写了这段代码:
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
如果这有助于理解发生了什么,我发出了以下命令,结果在要点 link 中:https://gist.github.com/nacho4d/94fdb72d8a3fee0c09e5
$ swiftc \
-emit-ir /Users/nacho4d/Desktop/function2/function2/main.swift \
-sdk Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk
来自 Swift 文档中的 "Functions"(强调已添加):
External Names for Parameters with Default Values
In most cases, it is useful to provide (and therefore require) an external name for any parameter with a default value. This ensures that the argument for that parameter is clear in purpose if a value is provided when the function is called.
To make this process easier, Swift provides an automatic external name for any parameter that has a default value. The automatic external name is the same as the local name, as if you had written a hash symbol before the local name in your code.
所以你的第一个函数声明
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
)。这就是你得到 "unexpected" 输出的原因。
如果将第一个函数的声明改为
func DoIt(a: Int, b: Int, _ c : Int = 0) -> Int
(其中 _
代表 "no external parameter name")
然后你会得到预期的输出:
DoIt(4, 5, 6) // result: 15