当采用协议时,为什么在struct
上实现方法前必须插入mutating
关键字?
而在class
中做同样的事情时为什么不需要mutating
?
当采用协议时,为什么在struct
上实现方法前必须插入mutating
关键字?
而在class
中做同样的事情时为什么不需要mutating
?
如果你要修改结构体中包含的任何状态,那么必须使用mutating关键字。由于Swift结构体是不可变对象,调用mutating函数实际上会原地返回一个新的结构体(就像将inout参数传递给函数一样)。mutating关键字让调用者知道该方法将会改变结构体的值。最好的理解方式是将结构体视为数字:如果执行操作4 + 1,4并没有变成5,只是在执行操作后得到了一个新值。mutating函数的操作也遵循同样的原则。你不能在常量上调用mutating函数(例如let someStruct = SomeStruct()
),因为这相当于试图将常量分配给一个新值。由于这种行为,mutating函数只能在变量上执行(例如var someStruct = SomeStruct()
)。
值类型的结构体是不可变的。这意味着其他变量不能在任何给定点更改结构体实例的值。
“mutating”关键字仅在更改结构体函数内部的自身变量值时需要。
例如:
struct MyStruct {
var abc: String = "initila value"
func changeValue() {
abc = "some other value". //Compile time error: Cannot assign to property: 'self' is immutable. Mark method 'mutating' to make 'self' mutable.
}
}
由于我们试图在结构声明中定义的函数内更改变量 abc 的值,因此我们会得到编译时错误。
因此,在这里我们需要使函数可变才能在结构体内更改值。 因此,正确的代码将是:
struct MyStruct {
var abc: String = "initila value"
mutating func changeValue() {
abc = "some other value"
}
}
编辑:
在声明协议时,可以通常为引用类型和值类型声明,因此这种协议本身声明函数作为mutating,以便它可以被类和结构体都采用。
由于是引用类型,所以在类中移除(或者说不需要)mutating关键字,但是对于值类型的结构体,则需要使用mutating关键字。
来自文档:
如果您定义了一个旨在改变采用该协议的任何类型的实例的协议实例方法需求,请将该方法与mutating关键字一起标记为协议定义的一部分。这使得结构和枚举可以采用协议并满足该方法要求。
如果将协议实例方法需求标记为mutating,则在编写类的该方法实现时无需编写mutating关键字。mutating关键字仅由结构和枚举使用。
希望这能解决您的疑问。
类是引用类型。这意味着一个变量被赋予类的类型:
let someObject = SomeClass()
仅包含对该类内存的指针,在幕后。由于它只是一个引用,所以类的内容和数据可以更改而不更改原始指针。
另一方面,结构体是值类型。如果您有一个包含结构体类型的变量:
var someStruct = SomeStruct()
这个变量实际上包含了整个结构体的数据。改变结构体的内部状态实际上涉及重新分配变量 - 因此在上面的例子中,类似someStruct.foo = "bar"
这样的操作实际上会导致变量someStruct
被重新分配,就好像你输入了:
someStruct = SomeStruct(foo: "bar", otherStuff: someStruct.otherStuff) // or something of this nature
var
声明结构体,而对于类则不需要这样做。