К какому типу относятся структура и класс в Swift: value type или reference type
Что проверяют
Знаете ли вы семантику копирования, а не только определение. Следом почти всегда спрашивают, что происходит с классом внутри структуры, как работает copy-on-write и когда вы всё-таки выберете класс.
Как отвечать
Структура, перечисление и кортеж в Swift это value types, класс и замыкание это reference types. Дальше конкретика:
- копирование: при присваивании и передаче в функцию структура копируется, у каждой переменной своё значение. Класс передаёт ссылку, и изменение через одну переменную видно через другую;
- изменяемость: у структуры, объявленной через
let, свойства менять нельзя, а методы, меняющие состояние, помечаютсяmutating. У классаletфиксирует только ссылку, свойства объекта меняются свободно; - память: экземпляры классов живут в куче и учитываются ARC, отсюда retain cycles и
weak/unowned. Структура обычно обходится без подсчёта ссылок, но «структура всегда на стеке» неправда: захваченная escaping-замыканием или крупная структура вany Protocolокажется в куче; - copy-on-write:
Array,Dictionary,Stringкопируют буфер только при записи в разделяемую копию. Для своих структур это не работает само, COW пишут вручную черезisKnownUniquelyReferenced; - возможности класса: наследование,
deinit, идентичность через===. Структура этого не умеет, поведение переиспользуется через протоколы.
Правило из документации Apple: по умолчанию берите структуру. Класс нужен, когда важна идентичность объекта или общее изменяемое состояние (менеджер сессии, кеш), либо когда этого требует Objective-C API. В SwiftUI сами вью это структуры, а состояние держат классы с @Observable. Для строгой проверки параллелизма в Swift 6 value types проще сделать Sendable.
Где спотыкаются
Говорят «структура на стеке, класс в куче» и строят на этом выводы о скорости. Размещение решает компилятор, а структура с десятком String при копировании гоняет счётчики ссылок своих полей.
Забывают, что структура с полем-классом копирует только ссылку: две копии меняют один и тот же объект, и семантика значения ломается.
Путают let у класса и структуры и уверены, что let делает объект класса неизменяемым.