Mutating Function Inside Class

Mutating function inside class

From The Language Guide - Methods:

Modifying Value Types from Within Instance Methods

Structures and enumerations are value types. By default, the
properties of a value type cannot be modified from within its instance
methods.

However, if you need to modify the properties of your structure or
enumeration within a particular method, you can opt in to mutating
behavior for that method. The method can then mutate (that is, change)
its properties from within the method, and any changes that it makes
are written back to the original structure when the method ends. The
method can also assign a completely new instance to its implicit self
property, and this new instance will replace the existing one when the
method ends.

You can opt in to this behavior by placing the mutating keyword before
the func keyword for that method ...

Hence, we need to include the keyword mutating to allow a member (e.g. a function) of a value type to mutate its members (e.g. the member properties of a struct). Mutating a member of a value type instance means mutating the value type instance itself (self), whereas mutating a member of a reference type instance will not mean the reference of the reference type instance (which is considered self) is mutated.

Hence, since a class is a reference type in Swift, we need not include the mutating keyword in any of the instance methods of your Zombie class, even if they mutate the instance members or the class. If we were to speak of mutating the actual class instance fredTheZombie, we would refer to mutating its actual reference (e.g. to point at another Zombie instance).

[†]: As another example, we may use e.g. mutating getters (get); in which case we need to mark this explicitly as these are nonmutating by default. Setters (set), on the other hand, are mutating by default, and hence need no mutating keyword even if they mutate members of a value type.

Is it possible to write mutating function in swift class?

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

What happens when a Class conforms to a protocol, which contains mutating function?

I don't see what the "confusion" is. You've elucidated the rules beautifully! A struct may implement a protocol's mutating function as nonmutating, but it may not implement a protocol's nonmutating function as mutating. Once you've said those rules, there's nothing to be "confused" about. The rules are the rules.

Classes don't have mutating functions so your investigations there are sort of irrelevant. If you had declared your protocol as a class protocol, your mutating annotation in the protocol would have been illegal.

Mutating function inside structure

I actually found the problem.. and it was pretty stupid.. I just had to change the "completed" part of the function, like this:

 mutating func getUserWorkspace(base: String, completed: @escaping (_ arr:[Workspace]?) -> ()){
let url = URL(string: "SOME URL")!
var request = URLRequest(url: url)

request.addValue("Basic \(base)", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Accept")

URLSession.shared.dataTask(with: request){ (data, response, error) in
if error == nil {
do {
let rep = try JSONDecoder().decode([Workspace].self, from: data!)
DispatchQueue.main.async {
completed(rep)
}
}catch {
print(error)
}
}
}.resume()
}

How to pass a class object to a function but prevent mutation?

This is extremely common throughout Cocoa. You create an immutable class and a mutable subclass. For examples, see AVComposition/AVMutableComposition, CBService/CBMutableService, CNContact/CNMutableContact.

In ObjC, this is common practice with collections as well (arrays, dictionaries, etc), but since those are value types in Swift, there's no need to use the classes (NSArray/NSMutableArray).

In Swift, rather than creating two classes, you create an immutable protocol and a class:

protocol Person: AnyObject {
var name: String { get }
var address: String { get }
}

class MutablePerson: Person {
var name: String = ""
var address: String = ""
}

Now, any function that accept Person will have an immutable object, and any function that accepts MutablePerson will be able to mutate it. This is a general pattern you can use to give different parts of your program access to different slices of the object's API. It's much more general and flexible than just const.

That said, this is not as common a pattern in Swift as it is in ObjC, since in most cases where this is useful, the type should be a struct anyway. But it is absolutely available if needed.


To your question about doing this with two classes, as in ObjC, it's possible, as long as you define both in the same file. It's just a bit tedious:

public class Person {
public fileprivate(set) var name: String = ""
public fileprivate(set) var address: String = ""
}

public class MutablePerson: Person {
public override var name: String {
get { super.name }
set { super.name = newValue }
}
public override var address: String {
get { super.address }
set { super.address = newValue }
}
}

It's possible a property wrapper could improve this, but I haven't been able to figure out how.

kotlin calling a mutating function in class delegation

Change

class Superman(override var position: Pair<Int, Int>): Walker by People(position)

to

class Superman(position: Pair<Int, Int>): Walker by People(position)

This way you only pass the initial value of position to the delegate instead of once more overriding position, which replaces the implementation that was originally delegated to Person.

Why does this Swift struct require mutating ?

Yes it is the default behaviour for a struct or enum that instance methods can not modify a property since they are value type. So you need to use mutating to override this behaviour.

The way you define your property, var or let, is still relevant for if you can change it from a mutable instance method or directly or not.

Since your property is not private you can still do

var g = Game(map: [[1]])
g.map.append([2])


Related Topics



Leave a reply



Submit