什么是下划线代表在Swift参考?
在苹果的文档的参考部分中有很多这样的事情:
func runAction(_
action
: SKAction!)
Objective-C的“等值”是这样的:
- (void)runAction:(SKAction *)
action
这让我觉得(在Swift引用中)在下划线之后有一个空格,而“action”用斜体字写的可能很重要。
但我无法弄清楚这是在传达什么。 所以也许问题是…是否有参考文献中使用的约定的参考?
– 这里是我引用这个引用下划线使用的页面: https : //developer.apple.com/documentation/spritekit/sknode#//apple_ref/occ/instm/SKNode/runAction
更新
Swift 3对如何使用和命名函数/方法参数名称和参数标签做了一些更改。 这对这个问题及其答案有影响。 @Rickster在解决这个问题的函数中做了一个关于_underscores的不同问题,这个问题做得非常出色: 为什么我需要快速的下划线?
两个答案都是正确的,但我想澄清一点。
_
用于修改方法的外部参数名称行为 。
在文档的“ 方法的本地和外部参数名称”部分,它说:
Swift在默认情况下给方法中的第一个参数名称一个本地参数名称,并且默认给出第二个和后续的参数名称本地和外部参数名称 。
另一方面,默认的函数没有外部参数名称。
例如,我们在Bar
类中定义了这个foo()
方法:
class Bar{ func foo(s1: String, s2: String) -> String { return s1 + s2; } }
当你调用foo()
,它被称为bar.foo("Hello", s2: "World")
。
但是 ,你可以通过在声明它的s2
前面使用_
来覆盖这个行为。
func foo(s1: String, _ s2: String) -> String{ return s1 + s2; }
然后,当你调用foo
,它可以简单的叫做bar.foo("Hello", "World")
而不需要第二个参数的名字。
回到你的案例, runAction
是一个方法,因为它显然与SKNode
types相关联。 因此,放置一个_
之前的参数action
可以让你在没有外部名字的情况下调用runAction
。
更新Swift 2.0
现在函数和方法在本地和外部参数名称声明方面的工作方式相同 。
现在使用外部参数名默认调用函数,从第二个参数开始。 这个规则只适用于纯Swift代码。
因此,通过在函数前面提供一个_
,调用者不必指定外部参数名称,就像您为某个方法所做的一样。
下划线是用于表示丢弃值的通用标记。
在这个特定情况下,这意味着该函数将被调用为runAction(argument)
而不是runAction(action:argument)
在其他情况下,它具有其他类似的含义,例如:
for _ in 0..<5 { ... }
这意味着我们只需要执行5次块,我们不关心块内的索引。
在这种情况下:
let (result, _) = someFunctionThatReturnsATuple()
这意味着我们不关心元组的第二个元素是什么,只是第一个元素。
参数声明前面的标识符定义了一个外部参数名称。 这是调用者在调用函数时必须提供的名称:
func someFunction(externalParameterName localParameterName: Int)
如果你自己没有提供外部的名字,Swift为你定义的任何默认参数提供了一个自动的外部名字。 对外部参数名称使用下划线select此行为:
在定义参数时,可以通过编写下划线(
_
)而不是显式外部名称来退出此行为。
您可以在这里阅读关于这个行为的更多信息。
由于Swift 3 默认情况下需要所有参数标签。
您可以强制IDE使用_
隐藏参数标签。
func foo(a: String) { } func foo2(_ a: String) { }
称为foo(a: "abc")
和foo2("abc")
注意:只有当(外部)参数标签和(内部)variables名称同时出现时,才可以使用此参数 。 它是等效的 –
func foo(aa: String)
不会接受_
。
为什么苹果使用它?
你可以看到苹果正在跨API使用它。 Apple的库仍然是用Objective-C语言编写的(如果不是的话,它们共享相同的函数名称,这些名称是为Objective-C语法devise的)
像applicationWillResignActive(_ application: UIApplication)
这样的函数将会有冗余参数名称的application
,因为已经有了应用程序的函数名。
你的例子
func runAction(_ action: SKAction!)
会被调用, 而不会像_
runAction(action:)
这样的标记。 参数名称action
将是多余的,因为函数名称中已经有一个。 这是目的,为什么它在那里。
我认为这迫使Swift的一个惯例,使它更接近Objective-C,更好地匹配cocoa公约。 在objc中,你不(外部)命名你的第一个参数。 相反,按照惯例,您通常在方法名的后半部分包含外部名称,如下所示:
- (void)myFancyMethodWithFirstName:(NSString *)aFirstName lastName:(NSString *)aLastName; [someInstance myFancyMethodWithFirstName:@"John" lastName:@"Doe"];
要使Swift api调用与objc保持一致,您需要禁止第一个参数的外部参数名称。
func myFancyMethodWithFirstName(_ firstName:String, lastName:String); someInstance.myFancyMethodWithFirstName("John", lastName:"Doe")
实际上,用于定义方法的实际代码与Apple文档中的方法声明是有区别的。 我们以UIControl的addTarget:action:forControlEvents:方法为例,实际的代码是:
但是在文档中,它看起来像这样(注意_在目标之前):
在实际的代码中,当调用一个方法时,_用于使第二个或后续参数的外部名称不出现,而在docs中,_在参数的本地名称之前指示当您调用方法或函数时,不应该提供外部名称。
当一个函数被默认调用的时候没有外部名字,除非你提供了你自己的或者在之前(没有空格)加上一个参数的本地名字,例如,这是我们如何使用dispatch_after :
在文档中,它是这样的(注意三个):
函数声明的约定和我所描述的方法是一样的。
只是更直观。
正如你所看到的,只是省略一个本地参数名称。