class — що це, ключові поняття та принцип роботи в Swift

Автор: IT Sectr Опубліковано: 2026-06-17 Час читання: 8 хв

Class — це тип-посилання (reference type) у мові Swift, екземпляри якого передаються за посиланням, а не копіюються при присвоєнні. На відміну від структур, класи підтримують успадкування, деініціалізацію та автоматичний підрахунок посилань ARC для керування пам'яттю. За даними Swift Programming Language Guide, 2026, class необхідний для роботи з UI-фреймворками Apple (UIKit, AppKit) та реалізації патернів, що потребують спільної ідентичності об'єкта. Вибір між class та struct — одне з ключових архітектурних рішень у Swift.

Головне

  • Class — тип-посилання у Swift, де змінна зберігає посилання на об'єкт у купі, а не саме значення.
  • Успадкування — класи можуть успадковувати властивості та методи батьківського класу та перевизначати їх через override.
  • ARC — автоматичний підрахунок посилань звільняє пам'ять, коли на об'єкт не залишається сильних посилань.
  • Deinit — спеціальний метод, який викликається перед звільненням об'єкта для очищення ресурсів.
  • Ідентичність — оператори === та !== перевіряють, чи посилаються дві змінні на один і той самий екземпляр класу.

Що таке class у Swift?

Class — це складовий тип-посилання у Swift, який групує властивості та методи в єдину сутність із підтримкою успадкування та динамічної диспетчеризації. На відміну від struct, екземпляр класу створюється в купі (heap), а змінна зберігає посилання на цей екземпляр, а не самі дані.

Коли ви присвоюєте змінну класу іншій змінній, обидві посилаються на той самий об'єкт у пам'яті. Зміни через одне посилання видимі через інше — це фундаментальна властивість типів-посилань, яка використовується в патернах делегування, спостереження та спільного стану.

За даними документації Apple Swift, класи — єдиний спосіб працювати з UIKit та AppKit, де всі UI-компоненти успадковуються від UIView та UIViewController. Крім того, класи необхідні для реалізації патернів, що потребують ідентичності об'єкта (два посилання на один об'єкт) та контрольованого часу життя.

Class як тип-посилання

Семантика типу-посилання — ключова властивість класів. При присвоєнні класу новій змінній Swift копіює посилання, а не дані. Всі змінні, що посилаються на один екземпляр, бачать його поточний стан і можуть його змінювати. Ця поведінка принципово відрізняється від типів-значень, де кожна змінна отримує незалежну копію.

swift
// Приклад семантики типу-посилання
class User {
    var name: String
    init(name: String) { self.name = name }
}

let user1 = User(name: "Alice")
let user2 = user1           // user2 — те саме посилання
user2.name = "Bob"

print(user1.name)               // "Bob" — змінено через user2!

// Перевірка ідентичності оператором ===
print(user1 === user2)          // true — той самий об'єкт

Оператори === (ідентичність) та !== перевіряють, чи посилаються дві змінні на один і той самий екземпляр класу. Це відрізняється від == (рівність), яке порівнює значення властивостей. Оператор === недоступний для struct — типи-значення не мають ідентичності.

Успадкування класів

Успадкування — механізм, за якого клас може перейняти властивості та методи батьківського класу. У Swift клас може успадковувати лише від одного батька (одинарне успадкування), але може реалізовувати безліч протоколів. Ключове слово override дозволяє перевизначити успадкований метод або властивість.

Базовий клас і підклас

Будь-який клас, який не успадковує від іншого класу, автоматично стає базовим (не плутати з NSObject). Підклас вказує батька через двокрапку після свого імені. Якщо підклас перевизначає метод батька, він зобов'язаний викликати super.метод() для збереження батьківської поведінки — це обов'язкова вимога компілятора.

Final клас

Ключове слово final перед class забороняє успадкування. Компілятор може оптимізувати виклики методів final-класу через статичну диспетчеризацію, що підвищує продуктивність. Використовуйте final для класів, які не призначені для розширення — це документує ваш намір і прискорює код.

swift
// Приклад успадкування класів у Swift
class Vehicle {
    var speed: Double = 0

    func description() -> String {
        "Speed: \(speed) km/h"
    }
}

// Car успадковує Vehicle
class Car: Vehicle {
    var brand: String = "Unknown"

    override func description() -> String {
        "\(brand) - \(speed) km/h"
    }
}

// Final клас — запобігає успадкуванню
final class ElectricCar: Car {
    var batteryLevel: Double = 100
}

let tesla = ElectricCar()
tesla.brand = "Tesla"
tesla.speed = 120
print(tesla.description())  // "Tesla - 120.0 km/h"

Успадкування класів — потужний, але відповідальний механізм. Глибока ієрархія (5+ рівнів) ускладнює підтримку та тестування. Для повторного використання функціональності без успадкування використовуйте протоколи з extension та протокольно-орієнтоване програмування — підхід, який Apple просуває як альтернативу глибоким class-ієрархіям.

Деініціалізація та керування пам'яттю

Swift використовує ARC (Automatic Reference Counting) для керування пам'яттю класів. Кожен екземпляр класу має лічильник сильних посилань. При створенні нового сильного посилання лічильник збільшується; при знищенні — зменшується. Коли лічильник досягає нуля, пам'ять звільняється.

Deinit

Deinit — метод, який викликається автоматично перед звільненням екземпляра класу. У ньому звільняють ресурси: закривають файли, відписуються від сповіщень, зупиняють таймери. Deinit є тільки у класів — у структур та перерахувань його немає.

Слабкі та безхазяйні посилання

Для запобігання циклам сильних посилань (retain cycles) Swift надає weak та unowned посилання. Weak — опціональне посилання, яке автоматично стає nil при звільненні об'єкта. Unowned — неопціональне, але посилається на об'єкт, який гарантовано живе довше поточного контексту. Типовий retain cycle виникає у відношенні батько-дитина: дитина зберігає сильне посилання на батька.

swift
// Приклад ARC та слабкого посилання
class Parent {
    var name: String
    var child: Child?

    init(name: String) { self.name = name }
    deinit { print("\(name) звільнено") }
}

class Child {
    var name: String
    weak var parent: Parent?   // weak запобігає retain cycle

    init(name: String) { self.name = name }
    deinit { print("\(name) звільнено") }
}

var parent: Parent? = Parent(name: "Anna")
parent?.child = Child(name: "Mia")
parent?.child?.parent = parent

parent = nil  // Обидва об'єкти звільнено!
// Без weak створив би retain cycle

Завжди використовуйте weak для посилань від дочірнього об'єкта до батьківського та для списків захоплення в замиканнях. Unowned використовуйте лише коли впевнені, що об'єкт переживе поточний контекст — неправильне використання unowned може призвести до краху при зверненні до звільненої пам'яті.

Class vs Struct: ключові відмінності

Вибір між class та struct — архітектурне рішення, яке впливає на продуктивність, безпеку потоків та дизайн API. Розгляньмо таблицю ключових відмінностей, яка допоможе прийняти правильне рішення в кожному конкретному випадку.

Характеристикаclassstruct
ТипТип-посиланняТип-значення (копія)
Пам'ятьКупа (heap) + ARCСтек / inlined
УспадкуванняПідтримує (один батько)Не підтримує
DeinitЄНемає
Ідентичність (===)ПідтримуєНе підтримує
MutatingНе потрібно (завжди mutating)Тільки з mutating
Memberwise initНе генеруєтьсяГенерується автоматично
Безпека потоківНе гарантована (спільний стан)Гарантована (копіювання)

Використовуйте класи, коли потрібна спільна ідентичність (кілька частин коду працюють з одним об'єктом), успадкування або взаємодія з Objective-C runtime. Для всього іншого переважні структури — вони швидші, безпечніші в багатопотоковому коді та не потребують керування пам'яттю.

Коли використовувати class у Swift

Незважаючи на рекомендацію Apple використовувати struct за замовчуванням, класи необхідні в кількох конкретних сценаріях. Розгляньмо кожен із практичними прикладами.

Компоненти UIKit та AppKit

Всі UI-компоненти в iOS та macOS — класи, які успадковують від UIView (iOS) або NSView (macOS). Ви не можете замінити UIViewController на структуру — він потребує успадкування та deinit для звільнення ресурсів. При роботі з UIKit використовуйте класи для контролерів, view та їхніх делегатів.

Singleton та спільний стан

Патерн Singleton (один екземпляр класу на весь застосунок) потребує семантики посилань. Менеджери: NetworkManager, SettingsManager, AnalyticsService — зазвичай реалізуються як класи з shared static властивістю. Структури не підходять, оскільки кожна копія буде незалежним екземпляром.

Впровадження залежностей та об'єкти-посилання

Коли об'єкт має бути єдиним джерелом істини та передається між модулями за посиланням — використовуйте class. Це стосується керування станом, де зміна об'єкта в одному місці має бути видимою у всіх залежних компонентах. Для ObservableObject у SwiftUI класи обов'язкові.

swift
// ObservableObject — class обов'язковий для SwiftUI
import SwiftUI

class AppViewModel: ObservableObject {
    @Published var isLoggedIn: Bool = false
    @Published var username: String = ""

    func login(user: String) {
        isLoggedIn = true
        username = user
    }
}

// Використання у SwiftUI View
struct ContentView: View {
    @StateObject var viewModel = AppViewModel()

    var body: some View {
        Text(viewModel.isLoggedIn ? "Ласкаво просимо" : "Увійти")
    }
}

Правило: якщо об'єкт повинен мати ідентичність (два посилання -> один об'єкт), бути єдиним екземпляром або працювати з UIKit/Objective-C — вибирайте class. Якщо об'єкт просто містить дані — вибирайте struct.

Поширені запитання

Що таке class у Swift?

Class — це тип-посилання у Swift, який підтримує успадкування, деініціалізацію та ARC для керування пам'яттю. Екземпляри класів зберігаються в купі, а змінні містять посилання на об'єкт, а не його копію.

Чим class відрізняється від struct у Swift?

Class — тип-посилання (передається за посиланням), підтримує успадкування та deinit. Struct — тип-значення (копіюється), не підтримує успадкування, але реалізує протоколи та отримує memberwise init автоматично. Swift рекомендує struct як тип за замовчуванням.

Що таке ARC у Swift?

ARC (Automatic Reference Counting) — механізм керування пам'яттю для класів Swift. Кожен екземпляр має лічильник сильних посилань. При обнулінні лічильника пам'ять звільняється. Weak та unowned посилання запобігають retain cycles між об'єктами.

Що таке deinit у Swift?

Deinit — метод класу, який викликається автоматично перед звільненням його пам'яті. Використовується для закриття файлів, відписки від сповіщень та інших завершальних операцій. Deinit є тільки у класів — у структур його немає.

Коли використовувати class у Swift?

Використовуйте class для UI-компонентів UIKit/AppKit, singleton, ObservableObject у SwiftUI, об'єктів зі спільною ідентичністю (delegate, observer) та при роботі з Objective-C runtime. Для моделей даних, DTO та конфігурацій переважна struct.

Підсумки

  • Class — це тип-посилання у Swift із семантикою передачі за посиланням: усі змінні, що вказують на один об'єкт, бачать його поточний стан і можуть його змінювати.
  • ARC керує пам'яттю класів через підрахунок сильних посилань; weak та unowned запобігають retain cycles у відносинах батько-дитина та замиканнях.
  • Успадкування дозволяє класам перевикористовувати та перевизначати поведінку батька, але глибока ієрархія (5+ рівнів) ускладнює підтримку коду.
  • Deinit виконується при звільненні об'єкта та обов'язковий для звільнення ресурсів — файлів, таймерів, підписок на NotificationCenter.
  • UIKit та AppKit потребують класів для всіх UI-компонентів — UIView, UIViewController, їхніх делегатів та data source.
  • ObservableObject у SwiftUI — class обов'язковий, оскільки SwiftUI відстежує зміни через @Published та @StateObject за посиланням.
  • Apple рекомендує struct як тип за замовчуванням для нових типів даних — використовуйте class тільки коли потрібна ідентичність, успадкування або інтеграція з Objective-C.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також