Struct — це тип-значення (value type) у мові Swift, екземпляри якого копіюються при передачі між ділянками коду. На відміну від класів, структури не підтримують успадкування, але реалізують протоколи, містять властивості та методи та забезпечують передбачуване керування пам’яттю без ARC. Згідно з Swift Programming Language Guide, 2026, struct є базовим будівельним блоком Swift — навіть стандартні типи Int, String, Array та Dictionary реалізовані як структури. Мова рекомендує структури як пріоритетний вибір для моделювання даних.
Головне
Struct (структура) — це складений тип даних у Swift, який групує пов’язані властивості та методи в єдину сутність. На відміну від класів, структури є value types: при передачі функції або присвоєнні новій змінній створюється незалежна копія структури, а не посилання на вихідний об’єкт.
Swift використовує структури для всіх примітивних типів: Int, Double, String, Bool, Array, Dictionary та Set. Це означає, що навіть базове число Int поводиться як структура — при присвоєнні створюється копія. Розробник може визначити власну структуру з довільним набором властивостей та методів.
За даними Swift Evolution (SE-0143), рішення реалізувати стандартні типи як структури зумовлене продуктивністю та передбачуваністю. Value types не створюють циклів посилань, не потребують підрахунку посилань ARC і гарантують, що зміна копії не вплине на оригінал — це критично важливо для імутабельності даних у багатопотокових сценаріях.
Семантика value type — ключова відмінність struct від class. Коли ви присвоюєте структуру новій змінній або передаєте її у функцію, Swift створює незалежну копію всіх даних. Будь-які зміни в копії не зачіпають оригінал, що виключає побічні ефекти, характерні для посилальних типів.
// Приклад семантики value type
struct Point {
var x: Double
var y: Double
}
var p1 = Point(x: 10, y: 20)
var p2 = p1 // p2 — незалежна копія p1
p2.x = 99 // Змінюється лише p2
print(p1.x) // 10 — p1 без змін
print(p2.x) // 99
Swift використовує Copy-on-Write (COW) для оптимізації копіювання. Якщо кілька змінних посилаються на одну структуру, але жодна з них не змінює дані, фактичного копіювання не відбувається. Swift ділить пам’ять між змінними до першої мутації — тоді створюється справжня копія. Це запобігає надмірним операціям виділення пам’яті та прискорює роботу з колекціями.
За замовчуванням методи структури не можуть змінювати її властивості — Swift вимагає явного вказання mutating для методів, які вносять зміни. Це обмеження захищає від випадкової мутації та робить код передбачуваним: якщо метод не позначений mutating, ви гарантовано не зміните структуру.
Коли ви додаєте ключове слово mutating перед методом, Swift отримує можливість записати нові значення у властивості структури. Фактично, метод може навіть повністю замінити екземпляр структури на новий через self =. Цей механізм використовується, наприклад, у типах Option та Result.
// Struct із mutating методом
struct Counter {
private var value: Int = 0
// Mutating метод — може змінювати властивості
mutating func increment() {
value += 1
}
// Mutating метод може повністю замінити self
mutating func reset() {
self = Counter()
}
// Non-mutating метод — лише читання
func currentValue() -> Int {
return value
}
}
var counter = Counter()
counter.increment()
print(counter.currentValue()) // 1
counter.reset()
print(counter.currentValue()) // 0
Правила для mutating: структура має бути оголошена через var, а не let — константній структурі не можна викликати mutating метод. Компілятор перевіряє це на етапі збірки: спроба викликати mutating метод на let-константі призведе до помилки компіляції.
Вибір між struct і class — одне з фундаментальних рішень у Swift. Обидва типи можуть містити властивості, методи, ініціалізатори та реалізовувати протоколи, але мають принципові відмінності в семантиці пам’яті, успадкуванні та керуванні життєвим циклом.
| Характеристика | struct | class |
|---|---|---|
| Тип | Value type (копіюється) | Reference type (посилання) |
| Успадкування | Не підтримує | Підтримує |
| ARC / підрахунок посилань | Не потрібен | Потрібен ARC |
| Деініціалізація | Не підтримує | Підтримує deinit |
| Зміна властивостей у константі | Тільки через var | Можна через let (посилання константне) |
| Type casting | Не підтримує | Підтримує |
| Зберігання в колекціях | Зберігається безпосередньо (значення) | Зберігається як посилання (вказівник) |
Структури кращі, коли дані не потребують успадкування, не повинні мати спільної ідентичності (наприклад, координати, розміри, конфігурація) та передаються між модулями. Класи обирають для UI-компонентів (UIView, UIViewController), сінглтонів та об’єктів зі спільною ідентичністю.
Apple рекомендує використовувати struct як тип за замовчуванням для моделювання даних у Swift. Структури підходять для більшості сценаріїв завдяки передбачуваній семантиці копіювання та відсутності накладних витрат на підрахунок посилань. Розглянемо типові випадки, коли struct — оптимальний вибір.
Якщо сутність містить дані без необхідності успадкування (Product, User, Order, Point), використовуйте struct. Компілятор автоматично генерує memberwise initializer — вам не потрібно писати init вручну. Equatable та Hashable також реалізуються автоматично для структур, усі властивості яких відповідають цим протоколам.
Для конфігурацій, налаштувань та прапорців, які не змінюються після створення, struct кращий за class. Константна (let) структура гарантує імутабельність усіх вкладених полів — у class це стосується лише посилання, а не вмісту об’єкта.
Структури безпечні в багатопотоковому середовищі через value semantics. Кожен потік отримує незалежну копію даних і не впливає на інші потоки. Гонки даних між потоками неможливі для value types, що робить struct кращим вибором для моделей у SwiftUI (ObservableObject потребує class, але @State використовує struct).
// Приклад використання struct для моделі даних
struct User: Codable, Identifiable {
let id: UUID
var name: String
var email: String
var isPremium: Bool
// Обчислювана властивість — non-mutating
var displayName: String {
isPremium ? "\(name) ⭐️" : name
}
}
// Автоматичний memberwise initializer
let user = User(
id: UUID(),
name: "Alice",
email: "alice@example.com",
isPremium: true
)
// Копіювання безпечне для багатопотоковості
var userCopy = user
userCopy.isPremium = false
// user.isPremium залишається true
Використовуйте class, коли потрібне успадкування (компоненти UIKit/AppKit), спільна ідентичність (delegate, observer) або контрольований час життя об’єкта (deinit). Для всього іншого — struct.
Часті запитання
Struct у Swift — це тип-значення (value type), який копіюється при передачі між ділянками коду. Структури можуть містити властивості, методи, ініціалізатори та реалізовувати протоколи. Базові типи Swift (Int, String, Array) реалізовані як структури.
Struct — value type (копіюється при присвоєнні), не підтримує успадкування та не потребує ARC. Class — reference type (передається за посиланням), підтримує успадкування, деініціалізацію та підрахунок посилань. Розробники рекомендують struct як тип за замовчуванням.
Mutating — ключове слово, яке вказує, що метод структури може змінювати її властивості. Без mutating компілятор забороняє модифікацію полів. Mutating методи можна викликати лише на змінних, оголошених через var, а не let.
Copy-on-Write (COW) — оптимізація Swift для структур, при якій фактичне копіювання даних відкладається до моменту першої мутації. Поки всі змінні лише читають структуру, вони поділяють одну область пам’яті. Це підвищує продуктивність при роботі з великими колекціями.
Використовуйте struct для моделей даних без успадкування, конфігурацій, DTO та багатопотокових сценаріїв. Використовуйте class для UI-компонентів UIKit/AppKit, сінглтонів, сутностей зі спільною ідентичністю (delegate, observer) та об’єктів, що потребують деініціалізації.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також