Swift 为什么我可以创建一个与函数参数同名的变量?

Swift 为什么我可以创建一个与函数参数同名的变量?,swift,Swift,在一个函数中,如果我被传递一个int(这是不可变的类型,也就是n),那么如果我把它传递到一个函数中,我怎么能创建一个var变量呢?只是想知道为什么斯威夫特是这样工作的,以及原因 func checkNum(_ n: Int) -> Bool { var n = n } 在这里,让我来做这件事。'var'作为参数属性在Swift 3中已被弃用,因此不再可能。您可以通过使用inout参数获得类似的行为 func checkNum(_ n: inout Int) -> Boo

在一个函数中,如果我被传递一个int(这是不可变的类型,也就是n),那么如果我把它传递到一个函数中,我怎么能创建一个var变量呢?只是想知道为什么斯威夫特是这样工作的,以及原因

func checkNum(_ n: Int) -> Bool {
    var n = n

}

在这里,让我来做这件事。

'var'作为参数属性在Swift 3中已被弃用,因此不再可能。您可以通过使用inout参数获得类似的行为


func checkNum(_ n: inout Int) -> Bool {
    n + 1
}

记住通过如下方式传递参数来调用函数:
checkNum(&n)
'var'作为参数属性在Swift 3中已被弃用,因此不再可能。您可以通过使用inout参数获得类似的行为


func checkNum(_ n: inout Int) -> Bool {
    n + 1
}
请记住通过如下方式传递参数来调用函数:
checkNum(&n)

这被称为“阴影”,允许在各种地方使用,因为这对程序员来说很方便,因为它避免了范围中有两个类似命名的变量。如果没有此功能,此代码将是:

func checkNum(_ n: Int) -> Bool {
    var writableN = n
    ...
}
这就增加了修改
writableN
,然后在函数中无意中再次使用
n
的可能性。由于额外的变量,这也会使函数更难理解。(当然,如果不小心使用,阴影也会使代码更难理解。)

这与if let阴影非常相似,例如:

var x: Int? = ...
if let x = x { ... }
这允许您在
if let
中使用
x
作为非可选项,而不必为其指定其他名称

这是一个相当普遍的特征。只要有一个新的作用域,变量就可以隐藏。例如,可以在函数中声明与属性或全局变量同名的变量。您也可以在函数内创建作用域

func checkNum(_ n: Int) -> Bool {
    var n = n  // Shadows previous `let`

    do {
        let n = 4 // Shadows previous `var`
        print(n)
    }

    return true
}
小心使用,这是有帮助的。使用太频繁(正如最后一个示例所做的那样),可能会使代码非常混乱

您的具体案例涉及Swift的另一个重要方面,即它试图控制共享的可变状态。函数接收的
n
是传递的整数的副本。修改
n
永远不会直接修改调用方的变量。(有
inout
允许这样做,但这很微妙。它不共享状态。它将值复制到中,并在返回时将值复制回。)

由于调用方不共享
n
,Swift通过使其不可变而使其非常明确。如果您想修改它,您需要显式地创建另一个副本,并且
var n=n
可以做到这一点。

这被称为“阴影”,允许在各种地方使用,因为这对程序员来说很方便,因为它避免了范围中有两个类似命名的变量。如果没有此功能,此代码将是:

func checkNum(_ n: Int) -> Bool {
    var writableN = n
    ...
}
这就增加了修改
writableN
,然后在函数中无意中再次使用
n
的可能性。由于额外的变量,这也会使函数更难理解。(当然,如果不小心使用,阴影也会使代码更难理解。)

这与if let阴影非常相似,例如:

var x: Int? = ...
if let x = x { ... }
这允许您在
if let
中使用
x
作为非可选项,而不必为其指定其他名称

这是一个相当普遍的特征。只要有一个新的作用域,变量就可以隐藏。例如,可以在函数中声明与属性或全局变量同名的变量。您也可以在函数内创建作用域

func checkNum(_ n: Int) -> Bool {
    var n = n  // Shadows previous `let`

    do {
        let n = 4 // Shadows previous `var`
        print(n)
    }

    return true
}
小心使用,这是有帮助的。使用太频繁(正如最后一个示例所做的那样),可能会使代码非常混乱

您的具体案例涉及Swift的另一个重要方面,即它试图控制共享的可变状态。函数接收的
n
是传递的整数的副本。修改
n
永远不会直接修改调用方的变量。(有
inout
允许这样做,但这很微妙。它不共享状态。它将值复制到中,并在返回时将值复制回。)


由于调用方不共享
n
,Swift通过使其不可变而使其非常明确。如果您想修改它,您需要显式地制作另一个副本,并且
var n=n
会这样做。

他没有声明他的参数属性
var
,而且
var
inout
的意思从来不是同一件事。他没有声明他的参数属性
var
,而
var
inout
的含义不同。参数和变量存在于不同的范围内。并且,您可以始终在内部作用域中创建名称类似于外部作用域中变量的变量。参数和变量存在于不同的作用域中。您可以在内部范围内创建与外部范围内的变量名称相似的变量。感谢您的详细解释!谢谢你的详细解释!