不同的用例之间有一些细微差别,但通常下划线表示“忽略这个”。
当声明一个新函数时,一个下划线告诉Swift参数在被调用时不应该有标签-这就是你所看到的情况。更完整的函数声明如下所示:
func myFunc(label name: Int) // call it like myFunc(label: 3)
"label"是一个参数标签,在调用函数时必须出现。(从Swift 3开始,默认情况下所有参数都需要标签。)"name"是你在函数中使用的参数的变量名。简短的形式是这样的:
func myFunc(name: Int) // call it like myFunc(name: 3)
这是一种快捷方式,允许您对外部参数标签和内部参数名称使用相同的单词。它等价于func myFunc(name name: Int)。
如果你想让你的函数在没有参数标签的情况下也可以被调用,你可以使用下划线_使标签为nothing/忽略。(在这种情况下,如果您希望能够使用参数,则必须提供一个内部名称。)
func myFunc(_ name: Int) // call it like myFunc(3)
在赋值语句中,下划线表示“不要赋值给任何东西”。如果你想调用一个返回结果但不关心返回值的函数,你可以使用这个。
_ = someFunction()
或者,就像你链接到的文章中那样,忽略返回元组的一个元素:
let (x, _) = someFunctionThatReturnsXandY()
在编写实现某些已定义函数类型的闭包时,可以使用下划线忽略某些参数。
PHPhotoLibrary.performChanges( { /* some changes */ },
completionHandler: { success, _ in // don't care about error
if success { print("yay") }
})
类似地,当声明一个采用协议或覆盖超类方法的函数时,可以使用_作为参数名来忽略参数。由于协议/超类也可能定义参数没有标签,因此您甚至可以在一行中以两个下划线结束。
class MyView: NSView {
override func mouseDown(with _: NSEvent) {
// don't care about event, do same thing for every mouse down
}
override func draw(_ _: NSRect) {
// don't care about dirty rect, always redraw the whole view
}
}
有点类似于后两种风格:当使用绑定局部变量/常量的流控制结构时,可以使用_来忽略它。例如,如果你想迭代一个序列而不需要访问它的成员:
for _ in 1...20 { // or 0..<20
// do something 20 times
}
如果你在switch语句中绑定元组情况,下划线可以作为通配符,就像这个例子(从Swift编程语言中的一个缩写而来):
switch somePoint { // somePoint is an (Int, Int) tuple
case (0, 0):
print("(0, 0) is at the origin")
case (_, 0):
print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
print("(0, \(somePoint.1)) is on the y-axis")
default:
print("(\(somePoint.0), \(somePoint.1)) isn't on an axis")
}
最后一件不太相关的事情,但我将包括它,因为(正如评论所指出的)它似乎把人们引向这里:标识符中的下划线-例如var _foo, func do_the_thing(), struct Stuff_ -对Swift没有什么特别的意义,但在程序员中有一些用途。
名字中的下划线是一种风格选择,但在Swift社区中并不受欢迎,因为Swift社区对类型使用UpperCamelCase,对所有其他符号使用lowerCamelCase有很强的约定。
在符号名前面加上下划线是一种风格约定,在历史上用于区分私有/仅供内部使用的符号与导出的API。然而,Swift对此有访问修饰符,所以这个约定在Swift中通常被视为非惯用的。
一些带有双下划线前缀的符号(func __foo())潜伏在苹果的sdk的深处:这些是(Obj)C符号,使用NS_REFINED_FOR_SWIFT属性导入Swift。当苹果想要做一个(Obj)C API的“更Swifty”版本时,他们就会使用这个方法——例如,把一个类型不可知的方法变成一个泛型方法。他们需要使用导入的API来使完善的Swift版本工作,所以他们使用__来保持它可用,同时对大多数工具和文档隐藏它。