В чем разница между ссылочным типом и типом значения в Swift?
Что проверяют
Понимаете ли вы семантику копирования и почему в Swift значение по умолчанию это структура.
Как отвечать
Значимые типы (struct, enum, кортежи, а также Array, String, Dictionary) копируются при присваивании и передаче. Ссылочные (class, замыкания) передают ссылку на один и тот же экземпляр.
struct P { var x = 0 }
var a = P(); var b = a; b.x = 5 // a.x остался 0
class C { var x = 0 }
let p = C(); let q = p; q.x = 5 // p.x стал 5Копирование дешевле, чем кажется: у стандартных коллекций работает copy-on-write, фактическое копирование буфера происходит только при изменении.
Практические следствия:
- значимый тип нельзя изменить неожиданно из другого места, поэтому он безопаснее в многопоточном коде и понятнее в отладке;
- ссылочный нужен там, где объект по смыслу один и его состояние разделяют: контроллер, менеджер сети, кэш. Ещё когда требуются наследование или
deinit; - у классов есть идентичность (
===), у структур только равенство по значению; letу структуры запрещает менять её поля, у класса запрещает менять саму ссылку, но не содержимое.
Правило языка: начинайте со struct, берите class, когда нужна разделяемая изменяемая ссылка.
Где спотыкаются
Считают копирование массива дорогим, не зная про copy-on-write.
Берут класс по привычке и ловят изменения через вторую ссылку.
Не понимают, почему let у класса позволяет менять свойства.
Забывают, что замыкание захватывает self сильно, и создают цикл ссылок.