Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the Swift 'mutating' keyword mean?

Tags:

swift

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?

like image 547
Coalabear Avatar asked Jul 02 '18 03:07

Coalabear


Video Answer


2 Answers

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()).

like image 163
Steven0351 Avatar answered Oct 21 '22 05:10

Steven0351


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).

like image 44
Charles Srstka Avatar answered Oct 21 '22 06:10

Charles Srstka