我无法理解添加此功能的意义所在。
将作为参数传递或由另一种方法调用的方法
func add(_ a : Int, _ b : Int) -> Int {
return a + b
}
从其他函数调用函数时
func average(_ a : Int, _ b : Int) -> Int{
return add(a, b) / 2
}
将函数作为其他函数的参数传递时
func averageArg(_ plus: (Int, Int) -> Int, _ a: Int, _ b : Int) -> Int {
return plus(a, b) / 2
}
答案 0 :(得分:0)
例如,如果没有函数“ postProcess”作为参数,则必须实现树函数:getAndAddData,getAndSubData和getAndMulData。
func add(_ a:Int, _ b:Int) -> Int {
return a + b
}
func sub(_ a:Int, _ b:Int) -> Int{
return a - b
}
func mul(_ a:Int, _ b:Int) -> Int{
return a * b
}
func getAndProcessData(_ postProcess:(Int, Int) -> Int, _ a:Int, _ b:Int) -> Int {
let a2 = ExampleClass.get(a)
let b2 = ExampleClass.get(b)
return postProcess(a2, b2)
}
func exampleFunc(a:Int, b:Int) {
let getAndAdd = self.getAndProcessData(self.add(_:_:), a, b)
let getAndSub = self.getAndProcessData(self.sub(_:_:), a, b)
let getAndMul = self.getAndProcessData(self.mul(_:_:), a, b)
}
答案 1 :(得分:0)
将函数用作参数的原因是它使函数更加灵活。通过传递将两个plus
值组合在一起的函数或闭包以返回Int
值,调用方可以决定Int
的作用。
例如,假设呼叫者希望plus
乘以值:
print(averageArg(*, 5, 6))
15
或采用两个值的max
(通过闭包):
print(averageArg({ max($0, $1) }, 1, 100))
50
一个更好的例子是Swift函数sorted(by:)
。 sorted
进行闭包,该闭包确定areInIncreasingOrder
的含义。这样,您只需更改传递的函数即可对数组进行升序和降序排序:
[1, 3, 2, 4].sorted(by: <)
[1, 2, 3, 4]
[1, 3, 2, 4].sorted(by: >)
[4, 3, 2, 1]
以下是使用函数的示例:
func shortNamesFirst(_ name1: String, _ name2: String) -> Bool {
if name1.count < name2.count {
return true
} else if name1.count > name2.count {
return false
} else {
// when names are the same length, sort
// them alphabetically
return name1 < name2
}
}
["Chuck", "Bob", "Bill", "Jo", "Ed", "Alexander"].sorted(by: shortNamesFirst)
["Ed", "Jo", "Bob", "Bill", "Chuck", "Alexander"]
sorted
的作者不必为用户可能想要的每种订购提供不同版本的sorted
。用户可以决定sorted
对他们的意义。
答案 2 :(得分:0)
您的示例并不是非常有说服力的使用传递闭包。但是,假设实现是可变的,即。您不知道在某些情况下会发生什么,使用闭包处理是一个很大的好处。举个例子:
func doSomething(with: AnyObject, whenFails failureClosure: ((Error) -> Void)? = nil) {
var error: Error?
// do stuff, maybe setting the error to something...
if let error = error,
let failureClosure = failureClosure {
failureClosure(error)
}
}
这允许调用者进行doSomething
,但通过传递闭包以自定义方式处理函数的失败。
这在异步情况下非常有用,在异步情况下,函数的结果用于执行某些操作,但无法在同一线程(例如,网络调用)中运行执行。
func doSomethingAsynchronously(completion completionClosure: (() -> Void)? = nil) {
// Do asynchronous stuff
if let completionClosure = completionClosure {
completionClosure()
}
}
答案 3 :(得分:0)
这是一个不经常使用的快速功能,但有时会非常方便。在您的示例中,这确实没有任何意义,但是让我们找到一个实际可行的方案。
首先让我们看看_ plus: (Int, Int) -> Int
的含义。该段代码意味着您的函数averageArg
接受任何接受两个整数参数并提供整数作为输出的 closure 或 function 。由于add(...)
符合此要求(两个integer
自变量,并提供integer
作为输出),因此您可以将其作为自变量传递。
但是让我们看一个这样的参数有意义的示例。可以说,我们正在为显示酒店评论的应用程序编写前端代码。在此应用程序中,我们需要在某处编写函数fetchReviews(_ serverResponse: ([Review]) -> Void)
,该函数可从某个远程服务器获取所有酒店评论:
struct Review {
let author: String
let rating: Int
}
func fetchReviews(_ completionHandler: @escaping ([Review]) -> Void) {
// Lets do a request to the server on a separate thread, so that the user can keep
// interacting with the app. The app doesn't freeze.
// Making qos .userInitiated will ensure that user interaction will be more important than
// our backend request.
DispatchQueue.global(qos: .userInitiated).async {
// Do some request to the server....
//...
// Lets pretend we have received a response, and we are turning the response into an array of reviews
completionHandler([Review]())
}
}
因为在服务器响应并给出所有评论之间以及调用fetchReviews
之间可能会有(有时很长)延迟,如果应用程序只是冻结,这对用户来说就不好了。相反,您可以在单独的线程上向服务器发出请求,以便用户可以继续使用该应用程序,并且该应用程序不会冻结(请参阅DispatchQueue.global
部分)。
但是,一旦我们收到服务器的回复,我们仍然希望向用户显示所有评论。通过添加_ serverResponse
参数,我们可以在实际上收到服务器的响应后立即通知调用fetchReviews
的任何人。这样,用户可以继续与该应用进行交互,一旦评论可用,我们就可以向用户显示评论!