Methods 为什么函数调用需要Swift中的参数名?
我在一个类中有这个函数:Methods 为什么函数调用需要Swift中的参数名?,methods,swift,named-parameters,Methods,Swift,Named Parameters,我在一个类中有这个函数: func multiply(factor1:Int, factor2:Int) -> Int{ return factor1 * factor2 } 我尝试使用以下方法调用函数: var multResult = calculator.multiply(9834, 2321) 问题是编译器希望它看起来更像这样: var multResult = calculator.multiply(9834, factor2: 2321) calc.multipl
func multiply(factor1:Int, factor2:Int) -> Int{
return factor1 * factor2
}
我尝试使用以下方法调用函数:
var multResult = calculator.multiply(9834, 2321)
问题是编译器希望它看起来更像这样:
var multResult = calculator.multiply(9834, factor2: 2321)
calc.multiply3(10.0, 10.0)
typealias FancyFunction = (f1: Double, f2: Double) -> Double
为什么第一个会导致错误 因为您在示例代码中使用了
calculator.multiply()
,所以我假设此函数是calculator
对象的方法
Swift从objective-c继承了很多东西,这就是其中之一:
在objective-c中,您将(假设)执行以下操作:
最重要的是:
针对Swift 2.0的更新:现在函数的行为与方法相同,默认情况下,对于这两种方法:
- 第一个参数没有外部名称;及
- 其他参数的外部名称与内部名称相同
#
速记语法现在已经消失
这里有一个更一般的答案:当定义为类外的真函数时,函数的行为与定义为方法时不同。此外,init方法有一个特殊的规则
功能 假设您定义了以下内容:
func multiply1(f1: Double, f2: Double) -> Double {
return f1 * f2
}
这里的参数名称仅为函数的本地,在调用函数时不能使用:
multiply1(10.0, 10.0)
如果要在调用函数时强制使用命名参数,可以。在每个参数声明前面加上其外部名称。这里,f1
的外部名称是f1param
,对于f2
,我们使用缩写,在前缀处加上#
,表示本地名称也将用作外部名称:
func multiply2(f1param f1: Double, #f2: Double) -> Double {
return f1 * f2
}
然后,必须使用命名参数:
multiply2(f1param: 10.0, f2: 10.0)
方法 方法不同。默认情况下,除第一个参数外,所有参数都已命名,如您所发现的。假设我们有这个,并考虑<代码>乘法1方法:
class Calc {
func multiply1(f1: Double, f2: Double) -> Double {
return f1 * f2
}
func multiply2(f1param f1: Double, f2: Double) -> Double {
return f1 * f2
}
func multiply3(f1: Double, _ f2: Double) -> Double {
return f1 * f2
}
}
然后,必须使用第二个(以及以下,如果有的话)参数的名称:
let calc = Calc()
calc.multiply1(1.0, f2: 10.0)
您可以通过为第一个参数提供外部名称(如函数)强制使用命名参数(如果要使用与其本地名称相同的外部名称,则可以在其本地名称前面加上#
)。然后,你必须使用它:
calc.multiply2(f1param: 10.0, f2: 10.0)
最后,您可以为以下其他参数声明一个外部名称。
,表示您希望在不使用命名参数的情况下调用方法,如下所示:
var multResult = calculator.multiply(9834, factor2: 2321)
calc.multiply3(10.0, 10.0)
typealias FancyFunction = (f1: Double, f2: Double) -> Double
互操作性注意:如果您在类Calc
前面加上@objc
注释,那么您可以从Objective-C代码中使用它,它与此声明等效(查看参数名称):
初始化方法
init
方法的规则略有不同,默认情况下,所有参数都有一个外部名称。例如,这是有效的:
class Calc {
init(start: Int) {}
init(_ start: String) {}
}
let c1 = Calc(start: 6)
let c2 = Calc("6")
在这里,您必须为接受Int
的重载指定start:
,但对于接受字符串的重载必须忽略它
互操作性注意:此类将导出到Objective-C,如下所示:
var multResult = calculator.multiply(9834, factor2: 2321)
calc.multiply3(10.0, 10.0)
typealias FancyFunction = (f1: Double, f2: Double) -> Double
闭包
假设您定义的闭包类型如下:
var multResult = calculator.multiply(9834, factor2: 2321)
calc.multiply3(10.0, 10.0)
typealias FancyFunction = (f1: Double, f2: Double) -> Double
参数名称的行为与方法中的名称非常相似。在调用闭包时,必须为参数提供名称,除非将外部名称显式设置为u
例如,执行闭包:
fund doSomethingInteresting(withFunction: FancyFunction) {
withFunction(f1: 1.0, f2: 3.0)
}
作为经验法则:即使您不喜欢它们,您也应该尝试至少在两个参数具有相同类型时继续使用命名参数,以便消除歧义。我还认为,至少命名所有Int
和Boolean
参数也很好。因为“乘法”函数是一种方法,与Objective-c一样,方法中的参数也是名称的一部分
例如,您可以这样做
class Calculator {
func multiply(factor1:Int, factor2:Int) -> Int{
return factor1 * factor2
}
func multiply(factor1:Int, factor2:Int, factor3:Int) -> Int{
return factor1 * factor2 * factor3
}
}
这里有两种不同的方法,具有不同的名称:乘法(factor2)和乘法(factor2 factor3)
此规则仅适用于方法,如果将其声明为类外的函数,则函数调用不需要参数名。原因是历史原因。这就是它在Smalltalk中的工作方式,它在后代中存活下来。斯奎克,目标C,斯威夫特
幼稚的语言(Squeak、Scratch和Blockly)坚持使用它,因为刚开始的程序员往往会在算术和参数顺序上挣扎。这就是Smalltalk这样做的最初原因。我不知道为什么ObjC和Swift决定通过该公约,但他们确实通过了
函数调用中的参数名称为关键字名,它们可以追溯到Smalltalk语言
类和对象通常从其他地方重复使用,或者构成非常大的复杂系统的一部分,并且在很长一段时间内不会有积极的维护注意
在这些情况下,提高代码的清晰性和易读性非常重要,因为当开发人员面临截止日期压力时,代码往往最终成为唯一的文档
为每个参数指定一个描述性的关键字名称,使维护人员能够通过浏览函数调用快速了解函数调用的目的,而不是深入研究函数代码本身。它使参数的隐含含义变得明确
在函数调用中为参数采用关键字名称的最新语言被描述为“一种运行速度极快、防止segfaults并保证线程安全的系统编程语言”
高正常运行时间系统需要更高的代码质量。关键字名称使开发和维护团队有更多的机会避免和捕获错误,因为发送错误的参数或无序调用参数
它们可以是罗嗦或简练的,但小人更喜欢罗嗦和描述性的,而不是简练和无意义的。他们可以负担得起