当定义一个闭包和一个具有相同名称的函数(比如foo
)和签名时,看起来好像闭包在调用时看起来优先(看似含糊不清)foo
。
// Int -> () function
func foo(num: Int) { print("function \(num)")}
// Int -> () closure
let foo: (Int) -> () = { print("closure \($0)")}
/* or...
let foo = { (num: Int) in print("closure \(num)")} */
foo(1) // closure 1
如果我选择 - 单击这两个声明,它们会在相关声明标签下相互指向,不同之处在于它们被称为:
声明:
func foo(num: Int)
相关声明:
foo
...
声明:
let foo: (Int) -> ()
相关声明:
foo(_:)
如果我们尝试为零参数函数定义相同的双foo
定义&关闭,我们得到一个编译时错误提示无效重新声明
// () -> () function
func foo() { print("function")}
// () -> () closure
let foo: () -> () = { print("closure")}
/* or...
let foo = { () in print("closure")} */
/* error: invalid redeclaration of 'foo' */
问题:为什么上面的第一个案例被认为是非模糊的,为什么在调用foo(..)
时闭包优先于函数(即,在重载决策中)是foo(...)
?
我无法找到任何官方文档(或现有的SO帖子)来解释这一点。
测试Swift 2.2 / Xcode 7.3和Swift 3.0-dev / IBM Sandbox(功能签名修改为func foo(_ num: Int) { ... }
)。
答案 0 :(得分:0)
在Swift中,如果没有传递参数,则不能将变量和函数或闭包命名为相同的东西。虽然我们以不同的方式调用它们(foo代表变量和foo()代表函数。我们将得到无效的foo重新声明。编译器将变量视为没有像函数那样的参数。考虑其中一些案例:
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
//in the arrayList we add the messaged received from server
arrayList.add(values[0]);
}
protected void onPostExecute (TCPClient result) {
mAdapter = new MyCustomAdapter(this, arrayList);
mList.setAdapter(mAdapter);
}
在这种情况下,class X {
var value : Int = 0
func value() -> Int { return 1 } // Invalid redeclaration of 'value()'
}
let x = X()
是什么?它是x.value
还是Int
将类的方法视为闭包是合法且有用的。
如果我们变得更加棘手,那该怎么办呢?
() -> Int?
Swift应该使用属性class X {
let value: () -> Int = { 2 }
func value() -> Int { return 1 } // Invalid redeclaration of 'value()'
}
let x = X()
let v = x.value() // ????
然后调用它吗?或者它应该调用方法value
闭包是完全合法的属性。
但是,使用参数,你可以命名一个函数和一个变量/ Closure相同的东西,虽然我建议你不要。在这种情况下,您应该尝试将变量和函数命名为描述它们是什么和/或它们如何使您的代码更易被其他人读取。我建议将变量命名为
value()?
因为通过命名函数,当你的方法和变量名相同时,它将允许用户确切地知道你正在调用哪个函数。用户可以知道他们正在传递什么参数。通过在调用下面的方法时命名。
class X {
// Int -> () function
func foo(number num: Int) { print("function \(num)")}
// Int -> () closure
let foo: (Int) -> () = { print("closure \($0)")}
}
你 CMD + 点击它会指向您为其编写的确切方法或变量/闭包。
考虑前面的例子:
let x = X()
x.foo(number: 2)
x.foo(3)
尽管您调用了正确的方法或闭包。通过 cmd + 点击,它只会指向关闭。