Rozważ tę klasę w Swift:
class Zombie: Monster {
var walksWithLimp = true
final override func terrorizeTown()
{
town?.changePopulation(-10)
super.terrorizeTown()
}
func changeName(name: String, walksWithLimp: Bool)
{
self.name = name
self.walksWithLimp = walksWithLimp
}
}
Zombie dziedziczy pole nazwy od klasy Monster.
var name = "Monster"
Dlaczego
fredTheZombie.changeName("Tom", walksWithLimp: true)
działa, nawet jeśli przed nagłówkiem funkcji nie ma słowa kluczowego mutującego?
Odpowiedzi:
12 dla odpowiedzi № 1Od Przewodnik językowy - metody:
Modyfikowanie typów wartości z metod wewnątrz instancji
Struktury i wyliczenia są wartość typy. Domyślnie właściwości typu wartości nie można modyfikować z poziomu jego instancji metody
Jeśli jednak musisz zmodyfikować właściwościtwoja struktura lub wyliczenie w ramach określonej metody, możesz włączyć mutowanie zachowanie dla tej metody. Metoda może następnie mutować (to znaczy zmieniać) jego właściwości w obrębie metody i wszelkie zmiany, które wprowadza są zapisywane z powrotem do oryginalnej struktury po zakończeniu metody. The Metoda może również przypisać całkowicie nową instancję do jej niejawnej
self
, a ta nowa instancja zastąpi istniejącą, gdy metoda się kończy.Możesz wyrazić zgodę na to zachowanie, umieszczając
mutating
słowo kluczowe wcześniej słowo kluczowe func dla tej metody ...
Dlatego musimy dołączyć słowo kluczowe mutating
aby zezwolić członkowi (np. funkcji†) wartość wpisz, aby zmutować jego członków (np. właściwości członka struct
). Mutowanie elementu instancji typu wartości oznacza mutowanie samej instancji typu wartości (self
), podczas gdy mutowanie członka odniesienie instancja typu nie będzie oznaczać odwołania do instancji typu odwołania (która jest brana pod uwagę self
) jest zmutowany.
Stąd, ponieważ a class
jest typem referencyjnym w Swift, nie musimy uwzględniać mutating
słowo kluczowe w dowolnej z Twoich metod instancji Zombie
klasa, nawet jeśli mutują członków instancji lub klasę. Gdybyśmy mieli mówić o mutowaniu rzeczywistej instancji klasy fredTheZombie
, odnosilibyśmy się do mutacji jego faktycznej odniesienie (np. aby wskazać inną Zombie
instancja).
[†]: Jako kolejny przykład możemy użyć np. mutating
getters (get
); w takim przypadku musimy to wyraźnie zaznaczyć nonmutating
domyślnie. Setery (set
), z drugiej strony są mutating
domyślnie i dlatego nie trzeba mutating
słowo kluczowe, nawet jeśli mutują członków typu wartości.
4 dla odpowiedzi nr 2
mutating
nie dotyczy klas, dotyczy tylko typów wartości, takich jak struct
i enum
1 dla odpowiedzi nr 3
Bez mutowania func
struct Counter {
let count: Int
init(count: Int = 0) {
self.count = count
}
// the functional approach
func counterByIncrementing() -> Counter {
let newCount = count + 1
return Counter(count: newCount)
}
}
var counter = Counter()
counter = counter.counterByIncrementing()
Mutowanie func
struct Counter {
// this now has to be a var :/
var count: Int
init(count: Int = 0) {
self.count = count
}
// the mutating keyword approach
mutating func increment() {
count += 1
}
}
var counter = Counter()
counter.increment()
W klasie wszystkie func mutują się. Ale dla struct i enum musimy sprecyzować.
1 dla odpowiedzi nr 4
Kolejny łatwy do zrozumienia przykład, zweryfikowany w Swift 3 i 4
struct City
{
var population : Int
func changePopulation(newpopulation : Int) {
population = newpopulation //error: cannot modify property "population"
}
}
var mycity = City(population : 500)
mycity.changePopulation(newpopulation : 2000) //error: cannot modify property "population"
Rozwiązanie
mutating func changePopulation(newpopulation : Int)