> Все ли нормально с рекурсивно ссылающейся на себя структурой (iOS, Swift)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: Сбер
Стек: iOS, Swift
> Пример ответа
Короткий ответ
Да, всё нормально, если структура ссылается на себя через reference type (class, closure) или косвенно через indirect enum. Прямая рекурсивная ссылка на value type (struct) невозможна - компилятор выдаст ошибку, потому что размер структуры становится бесконечным. Для этого используется indirect для enum или хранение ссылки на класс внутри структуры.
Подробное объяснение
Проблема в том, что структура - value type, и её память выделяется inline. Если структура содержит поле своего же типа, компилятор не может вычислить её размер: каждая структура содержит ещё одну структуру, та - ещё одну, и так до бесконечности.
SWIFTstruct Node {let value: Intlet next: Node? // ❌ error: value type 'Node' cannot have a stored property that recursively contains it}
Решение - сделать ссылку косвенной. Варианты:
- Класс внутри структуры - класс это reference type, хранится по ссылке, размер известен (8 байт на 64-битной платформе).
SWIFTfinal class NodeBox {var value: Intvar next: Node?init(value: Int, next: Node? = nil) { ... }}struct Node {let value: Intlet next: NodeBox?}
indirectдля enum - компилятор автоматически оборачивает рекурсивные case в ссылку.
SWIFTindirect enum LinkedList<Element> {case emptycase node(value: Element, next: LinkedList<Element>)}
- Замыкание - замыкание тоже reference type, но это менее удобно для структур данных.
Важно понимать trade-off: структура с ссылкой на класс перестаёт быть чисто value type - копирование структуры копирует ссылку, а не содержимое. Это нарушает семантику копирования, ожидаемую от структур. Если нужна value semantics, лучше использовать indirect enum или пересмотреть дизайн.
На практике
В реальном iOS-коде рекурсивные структуры встречаются редко. Чаще используют классы для деревьев, списков, графов. Если структура нужна для value semantics, indirect enum - самый чистый вариант: он сохраняет копирование по значению на верхнем уровне, а рекурсивные части оборачивает в ссылки автоматически.
Для простых случаев (например, дерево с двумя детьми) можно использовать класс-обёртку, но это добавляет мутабельность и reference semantics. Если структура маленькая и иммутабельная, indirect enum предпочтительнее - он даёт pattern matching и не требует ручного управления ссылками.
Пример кода
SWIFT// Вариант с indirect enum - сохраняет value semantics на верхнем уровнеindirect enum Tree<Element> {case leaf(Element)case node(Tree<Element>, Tree<Element>)}// Вариант с классом внутри структуры - проще, но reference semanticsfinal class BinaryNode<Element> {var value: Elementvar left: BinaryNode<Element>?var right: BinaryNode<Element>?init(_ value: Element) { self.value = value }}struct BinaryTree<Element> {var root: BinaryNode<Element>?}
Как отвечать на собеседовании
Начни с прямого ответа: "Да, но только через reference type или indirect". Объясни причину - бесконечный размер value type. Покажи два-три варианта решения, упомяни trade-off между value и reference semantics. Если спросят про производительность - отметь, что indirect enum добавляет уровень косвенности, но это незначительно. Хорошо добавить пример из практики: дерево, список, граф.
Что проверяет интервьюер
- Понимание разницы между value и reference type в Swift
- Знание ограничений структур (inline storage, фиксированный размер)
- Умение находить обходные пути для рекурсивных структур
- Понимание последствий для семантики копирования
Типичные ошибки
- Утверждение, что рекурсивная структура вообще невозможна - это неверно, возможна через ссылку
- Предложение использовать
classвместо структуры без объяснения trade-off - Игнорирование
indirectдля enum - многие забывают, что это ключевое слово существует - Непонимание, что копирование структуры с классом внутри копирует только ссылку, а не данные
> Похожие задачи по mobile
Что происходит с копированием при захвате структуры функцией без capture list
По какому времени работает функция reduce у массива
Как реализовать потокобезопасный словарь
Что должна возвращать функция сравнения
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью