【问题标题】:Can you override the variable definition inside closures?你可以覆盖闭包内的变量定义吗?
【发布时间】:2016-10-22 16:47:18
【问题描述】:

代码示例来自swift office document

let digitNames = [
    0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
    5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]

let strings = numbers.map {
    (number) -> String in
    var number = number //What is this!
    var output = ""
    while number > 0 {
        output = digitNames[number % 10]! + output
        number /= 10
}    
    return output
}

我对闭包体内的var number = number 线感到非常困惑。您如何“重新声明”具有相同范围的变量?

【问题讨论】:

  • (number) -> String 中,number 参数是一个常数。所以你用它做了一个 var ,它就变成了可变的。在作用域中,使用可变的一个,忽略另一个。这种“重新声明”只适用于函数范围内的函数参数。
  • @EricD:这也适用于其他本地范围,不仅适用于函数参数。
  • @MartinR Swift 3 关于这个属性有什么改变吗?
  • @MartinR 啊,是的,谢谢。这就是为什么我发表评论而不是完整答案的原因,我害怕错过或弄乱某些东西......我做到了。 :)
  • 顺便说一句,这正是 if let var = varguard let var = var else 正在做的事情。

标签: swift scope closures


【解决方案1】:

作用域中定义的常量或变量可以使用相同的名称 作为在外部范围中定义的另一个常量/变量。在这种情况下, 局部变量“隐藏”外部变量,但仅在其定义之后。 新变量的初始值可以参考外部变量 同名。示例:

func foo() {
    let x = 5
    do {
        var x = x
        //      ^-- The value of the outer constant `x`
        //  ^------ The local variable x
        x += 1
        print(x) // 6
    }
    print(x) // 5
}

一个常见的用例是制作函数参数的“变量副本”:

func digitsum(n : Int) -> Int {
    var s = 0
    var n = n
    while n > 0 {
        s += n % 10
        n /= 10
    }
    return s
}

同样的情况发生在你的闭包中:

let strings = numbers.map {
    (number) -> String in
    var number = number
    //           ^-- The number that the closure was called with
    //  ^----------- A local variable `number`
    var output = ""
    while number > 0 {
        output = digitNames[number % 10]! + output
        number /= 10
    }    
    return output
}

当然,您也可以为局部变量选择不同的名称。

在早期的 Swift 版本中,你可以声明一个函数参数 作为变量:

func digitsum(var n : Int) -> Int

但该功能在 Swift 2.2 中已被弃用并将被删除 在 Swift 3 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-13
    • 2013-03-29
    • 2014-06-22
    • 2019-01-05
    • 2018-08-26
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多