Protocol у Swift — це контракт, що визначає набір вимог, яким повинен задовольняти будь-який тип, що його прийняв. Протоколи лежать в основі протокол-орієнтованого програмування (POP) — парадигми, рекомендованої Apple для Swift поряд з класичним ООП. За даними Apple Documentation, 2026, структури, класи та enum можуть приймати протоколи, що робить архітектуру гнучкою та тестованою.
Головне
Protocol — це абстрактний інтерфейс, що визначає, що повинен уміти тип, але не як він це робить. У Swift протокол — аналог інтерфейсів з Java або Go, але з додатковими можливостями.
Протокол може вимагати:
{ get } або { get set }За даними WWDC 2015, Apple представила Protocol-Oriented Programming як фундаментальний підхід до архітектури Swift-додатків. На відміну від ООП, де успадкування класів створює жорсткі ієрархії, POP пропонує композицію протоколів. Це дає гнучкість: один тип може відповідати кільком протоколам, отримуючи їхні вимоги та реалізації через extensions.
Protocol оголошується ключовим словом protocol з іменем і тілом.
protocol Drawable {
func draw(context: CGContext)
var boundingBox: CGRect { get }
}
Тип приймає протокол через двокрапку після імені:
struct Circle: Drawable {
let center: CGPoint
let radius: CGFloat
func draw(context: CGContext) {
context.addArc(center: center, radius: radius, ...)
}
var boundingBox: CGRect {
CGRect(x: center.x - radius, y: center.y - radius,
width: radius * 2, height: radius * 2)
}
}
Один тип може прийняти кілька протоколів через кому: struct MyType: ProtocolA, ProtocolB. Компілятор перевіряє, що всі вимоги кожного протоколу виконані.
Вимоги властивостей вказуються з ключовим словом var і специфікаторами доступу { get } або { get set }.
protocol UserProtocol {
var name: String { get }
var age: Int { get set }
static var maxAge: Int { get }
mutating func updateName(_ newName: String)
}
Ключове слово mutating у протоколі означає, що метод може змінювати self. Структури повинні реалізувати такий метод як mutating, класи — можуть опустити. Вимоги методів вказуються з повною сигнатурою, включаючи мітки параметрів.
Protocol може успадковувати інший протокол, додаючи нові вимоги. Це створює ієрархію контрактів без жорсткої прив’язки до класів.
protocol Vehicle {
var speed: Double { get set }
func move()
}
protocol Flyable: Vehicle {
var altitude: Double { get set }
func takeOff()
}
Тип, що приймає Flyable, повинен виконати вимоги обох протоколів — і Vehicle, і Flyable. Swift підтримує множинне успадкування протоколів: protocol A: B, C.
Protocol Composition — механізм, що дозволяє вказати, що тип повинен відповідати кільком протоколам одночасно, без створення нового протоколу-комбінації.
func render(_ item: Drawable & Animatable) {
item.draw(context: ...)
item.animate(duration: 0.3)
}
Composition (&) працює в параметрах функцій, змінних і generic-обмеженнях. Компілятор перевіряє, що переданий тип одночасно задовольняє всі протоколи. Composition часто використовується в SwiftUI: some View — це generic із composition.
Protocol Composition є кращим за створення ієрархії успадкування: замість protocol A: B, C можна прийняти B & C безпосередньо. Це дає гнучкість і знижує зв’язаність. Composition особливо зручний у параметрах функцій і generic-обмеженнях, де потрібно тимчасово об’єднати вимоги без створення проміжного протоколу. Це знижує кількість допоміжних типів у коді.
Protocol може використовуватися як тип змінної, параметра функції або елемента колекції. Це називається existential type.
var drawableItem: Drawable
let items: [Drawable] = [Circle(...), Rectangle(...)]
func process(drawables: [any Drawable]) {
for item in drawables {
item.draw(context: ...)
}
}
Ключове слово any (Swift 5.6+) явно вказує на existential. Без any компілятор видає попередження. Swift також підтримує some (opaque types) для приховування конкретного типу за протоколом — це стандартний прийом у SwiftUI.
При роботі з протоколами розробники часто допускають кілька повторюваних помилок.
Drawable замість <T: Drawable> там, де потрібен конкретний типAnyObject без необхідності, що виключає struct та enumЧасто задавані питання
Protocol визначає тільки вимоги без реалізації (до protocol extensions). Abstract class може містити реалізацію та стан. У Swift немає abstract класів — їх роль виконують протоколи з extensions.
Так, структури, класи та enum — усі можуть приймати протоколи. Це основа POP: ви не зобов’язані використовувати класи для організації архітектури. Структури з протоколами дають value semantics та імутабельність.
Асоційований тип (associatedtype) — placeholder для типу, який реалізуючий тип визначає самостійно. Приклад: Collection має associatedtype Element. Це generic на рівні протоколу.
Так, додайте успадкування від AnyObject: protocol MyProtocol: AnyObject. Тоді тільки класи зможуть прийняти цей протокол. Це корисно для weak-посилань і делегатів.
Використовуйте is для перевірки та as? для приведення: if let drawable = item as? Drawable. Це працює тільки для протоколів без асоційованих типів.
Підсумки
&) комбінує протоколи без успадкуванняany) та opaque types (some) — два способи роботи з протоколамиМи розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.