使用let on变量变量

时间:2015-07-27 19:21:46

标签: swift

我有一个简单的自定义类,为了简单起见,在示例中假设它包含一个属性,它是一个字符串数组的数组。它有一个方法可以将第一个对象从一个数组移动到另一个数组。忽略丢失的初始化程序,这是我已编写的现有类的截断版本。

class MyClass: NSObject
{
    var strings:Array< Array< String > >

    func makeMove(fromArray:Int, toArray:Int)
    {
        var from = strings[fromArray] as Array< String >
        var to = strings[toArray]

        let top = from[0]
        to.append(top)
        from.removeAtIndex(0)

        towers[fromTower] = from
        towers[toTower] = to
    }
}

如果我声明MyClass的新实例并在其上调用此单个方法,我会收到编译器警告,指出该实例从未被修改过,应该是let而不是{{1 }}。

var

有趣的是,即使在第二个实例中它是一个var myInstance = MyClass() //Warning myInstance.makeMove(0, toArray:1) let myInstance = MyClass() //No warning myInstance.makeMove(0, toArray:1) ,它应该是一个常量,实际上实例在调用let时会发生变异。

这种情况有什么不对?我应该使用makeMove,还是编译器没有正确识别它是一个变异函数?

2 个答案:

答案 0 :(得分:2)

首先,确保您了解参考类型与价值类型。

https://developer.apple.com/swift/blog/?id=10

let关键字可以防止后者的变异,而不是前者。将let引用变量视为:变量引用的引用(内存地址)不能更改,但该内存的内容可以

因此警告试图告诉您,您永远不会将引用myInstance重新分配给另一个对象,但您的声明允许这种可能性。

如果您的设计myInstance应该始终引用它首先分配给它的对象,让编译器通过将其表示为let来帮助您。然后随意传递引用并根据需要使用引用的任何副本更改对象的内容。

答案 1 :(得分:0)

总而言之,根据wjl的建议,以下是我认为您想要的内容:

class MyClass {
    var strings : [[String]] = []

    func makeMove(fromArray from: Int, toArray to: Int) {
        let item = strings[from].removeAtIndex(0)
        strings[to].append(item)
    }
}

let a = MyClass()
a.strings = [["Hi", "H", "A", "C"], ["He", "Ab", "To", "Hehe"]]
a.makeMove(fromArray: 0, toArray: 1)
a.strings           // [["H", "A", "C"], ["He", "Ab", "To", "Hehe", "Hi"]]

// a = MyClass()    // error: cannot assign to value: 'a' is a 'let' constant

您仍然可以更改该对象的实例,但无法更改对象,a指向