我有一个简单的自定义类,为了简单起见,在示例中假设它包含一个属性,它是一个字符串数组的数组。它有一个方法可以将第一个对象从一个数组移动到另一个数组。忽略丢失的初始化程序,这是我已编写的现有类的截断版本。
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
,还是编译器没有正确识别它是一个变异函数?
答案 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
指向