在Swift中使用函数参数名称

15

在Swift中,当你调用一个方法时会使用参数名,除了第一个参数。为什么第一个参数的名称不会被使用?

以下是从Swift手册中摘录的一个例子:

var count2: Int = 0
func incrementBy2(amount: Int, numberOfTimes times: Int) {
count2 += amount * times}

这将可以工作;

incrementBy2(2, numberOfTimes: 7)

然而这给了我一个“在调用中有多余的参数标签‘amount’”

incrementBy2(amount: 2, numberOfTimes: 7)

这是有原因的,还是那种“就是这样”的事情?

5个回答

18

这是为了沿用我们在 Objective-C 中习惯的约定,即将第一个参数的名称与方法名称结合在一起。以下是一个例子:

- (void)incrementByAmount:(NSInteger)amount
            numberOfTimes:(NSInteger)times
{
    // stuff
}
你可以这样调用该方法:
[self incrementByAmount:2 numberOfTimes:7];

将参数名称纳入方法名称中,阅读起来更加自然。在Swift中,可以通过以下方式实现:

func incrementByAmount(amount: Int, numberOfTimes: Int) {
    // same stuff in Swift
}

然后像这样调用该方法:

incrementByAmount(2, numberOfTimes: 7)

如果您不希望使用这种约定,Swift 允许您更加明确地定义单独的内部和外部参数名称,例如:

func incrementByAmount(incrementBy amount: Int, numberOfTimes: Int) {
    // same stuff in Swift
    // access `amount` at this scope.
}
你可以这样调用该方法:
incrementByAmount(incrementBy: 2, numberOfTimes: 7)

2
谢谢。现在这个概念非常清晰易懂了。尴尬的是,虽然它看起来很简单,但我没有理解它。 :-) - Razor
1
注意:现在在Swift 2.0中,您将调用方法func incrementByAmount(amount amount: Int, numberOfTimes: Int) { }。移除#号并加倍参数名称 :) - Adam Carter

6

在你的例子中,你没有为第一个参数设置名称。你只有变量名。

请尝试以下:

func incrementBy2(amount am: Int, numberOfTimes times: Int) {
}

所以你可以把它称为

incrementBy2(amount: 0, numberOfTimes: 0)

并且am将会是函数内部的变量名,amount将是外部名称。

如果你想要相同的外部名称和变量,你可以尝试这样:

func incrementBy2(amount amount: Int, numberOfTimes times: Int) {
}

仍然像这样调用:

incrementBy2(amount: 0, numberOfTimes: 0)

更多信息请参阅苹果公司的The Swift Programming Language中的函数参数名称指定外部参数名称章节。


谢谢!我只看了书的21页,往后看更容易理解正在发生的事情。我现在明白使用#符号来使用本地参数名称的用途了。 - Razor
1
Swift已经移除了#符号。现在你应该只是双倍增加(例如func incrementBy2(amount amount: Int... - shim

3
在Swift中,方法与Objective-C中的方法非常相似。与Objective-C一样,Swift中方法的名称通常使用介词(如with、for或by)引用方法的第一个参数,例如前面Counter类示例中的incrementBy方法。使用介词使得在调用方法时可以将其读作一个句子。Swift通过为方法参数使用不同的默认方法来实现这种已有的方法命名约定,而不是像函数参数那样。具体而言,Swift默认将方法中的第一个参数名称设置为本地参数名称,并且默认给第二个及后续参数名称同时设置本地和外部参数名称。这种约定与编写Objective-C方法时您所熟悉的典型命名和调用约定相匹配,并且在不需要限定参数名称的情况下实现了表达式方法调用。

谢谢,这让我很明白。我还没有看到书的那一部分。 - Razor

1
它只是使用了与Objective C相同的模式,其中方法具有命名参数,除第一个参数外,该参数由方法名称本身定义。例如:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

你可以通过显式地添加名称或在参数名称前加上哈希#字符,将第一个参数转换为命名参数。
顺便说一下,在Objective C中,方法签名是方法名加上所有命名参数,例如:
- (void) addUser:(User *)user toArray:(NSMutableArray *)array

“is different than”不同于:
- (void) addUser:(User *)user toDict:(NSMutableDictionary *)dict

基本上和其他语言(如C#,Java等)一样:
void addUser(User user, Array array)

is different than:

void addUser(User user, Dictionary dict)

谢谢。我还没有读到那部分书,没注意到那个。 - Razor

1

为了更新这个Swift最新版本的答案,强制使用函数的第一个命名参数的#已经从语言中删除。为了指定外部参数名称,现在只需用空格将外部名称与内部名称分开即可。之前#用于表示参数在内部和外部具有相同的名称,但现在您必须在函数定义中重复参数名称以实现此目的:

var count2: Int = 0
func incrementBy2(amount amount: Int, numberOfTimes times: Int) {
  count2 += amount * times
}
incrementBy2(amount: 2, numberOfTimes: 7) // result is 14

为了更清晰明了,你还可以区分名称:

var count2: Int = 0
func incrementBy2(theValue amount: Int, numberOfTimes times: Int) {
  count2 += amount * times
  }
incrementBy2(theValue: 2, numberOfTimes: 7)

或者按照Objective-C的方式进行操作,并明确第一个参数应该是什么:

var count2: Int = 0
func incrementBy2TheValue(amount: Int, numberOfTimes times: Int) {
  count2 += amount * times
}
incrementBy2TheValue(2, numberOfTimes: 7)

我不确定人们对于函数名称中使用数字的感受如何。但是我意识到这只是一个例子。


我喜欢那个 # ... 不知道为什么要把它移除掉 - user89862

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