Reputation: 449
What does the Swift 'mutating' keyword mean, and why must I insert mutating
before implementing a method on a struct when adopting protocols?
Why don't I need mutating
when I do the same thing in a class?
Upvotes: 29
Views: 29125
Reputation: 870
The Mutating Keyword : In order to modify the properties of a value type, you have to use the mutating keyword in the instance method. With this keyword, your method can then have the ability to mutate the values of the properties and write it back to the original structure when the method implementation ends.
Class is not support In swift, classes are reference type whereas structures and enumerations are value types. The properties of value types cannot be modified within its instance methods by default. In order to modify the properties of a value type, you have to use the mutating keyword in the instance method.
Upvotes: 6
Reputation: 539
The mutating keyword is only required if you are changing any state contained within the struct. Since Swift structs are immutable objects, calling a mutating function actually returns a new struct in-place (much like passing an inout parameter to a function). The mutating keyword lets callers know that the method is going to make the value change. The best way to conceptualize this is to think of your struct the same as you would a number: if you perform the operation 4 + 1, 4 doesn’t become 5, you’ve just gotten a new value after performing the operation. Mutating functions operate on the same principle. You cannot call mutating functions on constants (e.g. let someStruct = SomeStruct()
), because that would be the same thing as trying to assign the constant to a new value. Because of this behavior mutating functions can only be performed on variables (e.g var someStruct = SomeStruct()
).
Upvotes: 36
Reputation: 1325
Being the value type structs are immutable. Meaning other variables can not change the values for instance of structure at any given point.
The mutating word is required for changing the values of self variables inside structure's function ONLY.
For. e.g
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.
}
}
Here as we are trying to change value of variable abc inside function declared in struct itself, we get the compile time error.
So here we need to make function mutating to make change value inside structure. Hence the correct code will be:
struct MyStruct {
var abc: String = "initila value"
mutating func changeValue() {
abc = "some other value"
}
}
EDIT:
When declaring protocol, it can be declared commonly for reference and value types, so these kind of protocols itself declares the functions as mutating so that it can be adopted by both classes and structures.
Since being reference type the mutating keyword is removed (or we can say not required) in the classes, but for structures being value types the mutating keyword is required.
From the docs:
If you define a protocol instance method requirement that is intended to mutate instances of any type that adopts the protocol, mark the method with the mutating keyword as part of the protocol’s definition. This enables structures and enumerations to adopt the protocol and satisfy that method requirement.
If you mark a protocol instance method requirement as mutating, you don’t need to write the mutating keyword when writing an implementation of that method for a class. The mutating keyword is only used by structures and enumerations.
I hope this will clear your doubt.
Upvotes: 19
Reputation: 17040
Classes are reference types. What that means is that a variable typed to a class:
let someObject = SomeClass()
just contains a pointer to that class's memory, under the hood. The class's contents and data can change without changing the original pointer, because it's just a reference.
Structs, on the other hand, are value types. If you have a variable containing something that is a struct type:
var someStruct = SomeStruct()
the variable itself is actually containing all the struct's data. Changing the struct's internal state actually involves reassigning the variable—so in the example above, something like someStruct.foo = "bar"
would actually cause the someStruct
variable to be reassigned, as if you'd typed:
someStruct = SomeStruct(foo: "bar", otherStuff: someStruct.otherStuff) // or something of this nature
This is also why you have to declare structs using var
if you plan to change anything in them, whereas this isn't so with classes.
As for protocols, they can represent either struct or class types, so if you are dealing with a protocol existential, you can't do operations on it that assume it's a class (unless the protocol is constrained as such).
Upvotes: 7