嵌套函数在swift中的实际用途是什么?

时间:2015-10-06 10:51:46

标签: swift function

嵌套函数的实际用途是什么?它只会使代码更难阅读,并且不会使特定情况变得容易。

func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { return input + 1 }
    func stepBackward(input: Int) -> Int { return input - 1 }
    return backwards ? stepBackward : stepForward
}

Source

4 个答案:

答案 0 :(得分:17)

我认为你问题的核心是:为什么不使用私有函数而不是丑陋的嵌套函数?

简单地说,嵌套函数可以带来更多可读性封装

仍然可以从班级中的其他功能访问私有功能。对嵌套函数来说,情况并非如此。您告诉开发人员,这只属于此功能(与私有功能相反,它们属于整个类)。如果你需要类似的能力,请退后一点,不要搞乱它,去写自己的!

另一个便利是它可以访问其父函数的所有本地参数。您不再需要传递它们。这最终意味着要测试的功能少一个,因为你已经将一个函数包装在另一个

另一个用例就是你班上的功能非常相似,比如你有:

extractAllHebrewNames() // right to left language
extractAllAmericanNames() // left to right language
extractAllJapaneseNames() // top to bottom language

现在,如果您有一个名为printName(打印名称)的私人功能,如果您根据语言切换案例,它会起作用,但如果您不能/不能这样做会怎样。相反,您可以在每个单独的提取函数中编写自己的嵌套函数*并打印名称。

您的问题有点类似,为什么不使用' if else'而不是切换案例。

我认为这只是一种便利(对于可以在不使用嵌套函数的情况下处理的事情)。

注意:嵌套函数应该在函数内的callsite之前写入。

错误:使用局部变量'嵌套'在宣布之前

func doSomething(){
    nested()

    func nested(){

    }
}

没有错误:

func doSomething(){
    func nested(){

    }

    nested()
}

类似地,必须在嵌套函数

之前声明嵌套函数中使用的局部变量

*:他们现在都可以拥有完全相同的名字。因为每个都在不同的命名空间。

答案 1 :(得分:1)

一个用例是对递归数据结构的操作

例如,考虑在二进制搜索树中搜索的代码:

func get(_ key: Key) -> Value? {
    func recursiveGet(cur: Node) -> Value? {
        if cur.key == key {
            return cur.val
        } else if key < cur.key {
            return cur.left != nil ? recursiveGet(cur: cur.left!) : nil
        } else {
            return cur.right != nil ? recursiveGet(cur: cur.right!) : nil
        }
    }

    if let root = self.root {
        return recursiveGet(cur: root)
    } else {
        return nil
    }
}

当然,您可以将递归转换为循环,取消嵌套函数。我发现递归代码通常比迭代变体更清晰。 (权衡与运行时成本!)

你也可以将recursiveGet定义为get之外的(私人)成员,但这样做会很糟糕(除非在多种方法中使用recursiveGet)。

答案 2 :(得分:0)

在您的示例中,您可以创建一个variable,它也是function,如下所示:

var myStepFunction = chooseStepFunction(true)

myStepFunction(4)

嵌套函数的好处非常好。例如,假设您正在为计算器构建应用程序,您可以将所有逻辑放在一个函数中,如下所示:

func doOperation(operation: String) -> ((Double, Double) -> Double)? {
    func plus(s: Double, d: Double) -> Double {
        return s + d
    }
    func min(s: Double, d: Double) -> Double{
        return s - d
    }
    switch operation {
        case "+":
            return plus
    case "-" :
        return min
    default :
        return nil
    }
}

var myOperationFunction = doOperation("-")?(4, 4) // 0
var myOperationFunction2 = doOperation("+")?(4, 5) //9

在某些情况下,您不允许查看某些功能的实现,或者不负责。然后将它们隐藏在其他函数中真的是一个很好的方法。例如,假设您的同事可以开发plusmin函数,他/她会这样做,您只需使用外部函数。

它不同于闭包,因为在clouser中,将你的逻辑传递给其他逻辑,这将调用你的逻辑。它是一种插件。例如,在调用http请求后,您可以在从服务器接收响应时传递您希望应用程序执行的代码

答案 3 :(得分:0)

原则(自Objective-C以来)“代码可以是数据”。您可以传递代码,将其存储在变量中,并将其与其他代码结合使用。这是极其强大的工具。坦率地说,如果我没有能力将代码视为数据,那么我编写的大部分代码将难以写入十倍,并且难以阅读十倍。

Swift中的函数只是闭包,因此嵌套函数非常有意义,因为当您不想使用众多可用快捷方式之一时,这就是编写闭包的方式。