То, как структура «объявлена» перед тем, как поместить ее в массив, на самом деле не имеет значения.Давайте поговорим о том, как вещи доступны из массива.
Я утверждаю следующую тестовую ситуацию:
struct Card {
var property : String
}
var cards = [Card(property:"hello")]
Мы пытаемся сказать
for card in cards {
card.property = "goodbye"
}
, но не можем, потому что card
неявно объявлено с let
и его свойства не могут быть изменены.Итак, давайте попробуем обойти это с помощью var
переназначения:
for card in cards {
var card = card
card.property = "goodbye"
}
Теперь наш код компилируется и запускается, но угадайте, что?Сам массив не затронут!Это потому, что card
является копией структуры, находящейся в массиве;и передача параметров и назначение делают копию.На самом деле мы могли бы сократить это, настаивая на var
ссылке заранее:
for var card in cards {
card.property = "goodbye"
}
Но мы ничего не получаем;card
по-прежнему является копией, поэтому содержимое массива по-прежнему не затронуто.
Итак, теперь давайте попробуем выполнить индексацию, как это было сделано в ваших экспериментах:
for ix in cards.indices {
cards[ix].property = "goodbye"
}
Бинго!Он компилирует и запускает , а изменяет содержимое массива cards
.Это потому, что мы обращаемся к каждой карточке напрямую в массиве.Это так же, как если бы мы сказали:
for ix in cards.indices {
var card = cards[ix]
card.property = "goodbye"
cards[ix] = card
}
Да, мы все еще делаем копию, но мы переназначаем эту копию обратно в то же место в массиве.Доступ к индексу является сокращением для этого.
Однако мы все еще на самом деле вытаскиваем копию, изменяем ее и снова вставляем.Мы можем попытаться обойти это, за счет некоторого более сложного планирования, используя inout
, например:
func mutate(card: inout Card) {
card.property = "goodbye" // legal!
}
for ix in cards.indices {
mutate(card: &cards[ix])
}
Как вы можете видеть, теперь мы можем установить card.property
,потому что с inout
параметр неявно равен var
.Однако, ирония в том, что мы все еще делаем копию и замену, потому что структура является типом значения - ее невозможно действительно изменить на месте, даже если присваивание через var
ссылка дает иллюзию, что мы делаем это.