Protocol — je soubor požadavků (vlastnosti a metody), kterým musí typ implementující daný protokol vyhovovat. Ve Swift jsou protokoly ústředním prvkem Protocol-Oriented Programming (POP), umožňujícím polymorfismus bez dědičnosti. Podle údajů Swift.org (2025) jsou protokoly použity v 85 % typů standardní knihovny Swift. V Objective-C plní @protocol podobnou roli, ale s omezením — pouze pro třídy.
Hlavní body
Protocol ve Swift — je abstraktní rozhraní definující požadavky, které musí typ splňovat. Protokol může vyžadovat vlastnosti (s getter/setter), metody (instance a typu), inicializátory a subscript. Na rozdíl od tříd mohou být protokoly implementovány strukturami, výčty a třídami — to poskytuje flexibilitu nedostupnou v čistě třídních jazycích.
protocol Drawable {
var boundingRect: CGRect { get }
mutating func draw(in context: CGContext)
}
struct Circle: Drawable {
var center: CGPoint
var radius: CGFloat
var boundingRect: CGRect {
CGRect(x: center.x - radius, y: center.y - radius,
width: radius * 2, height: radius * 2)
}
func draw(in context: CGContext) {
context.addEllipse(in: boundingRect)
}
}Struktura Circle implementuje protokol Drawable, poskytující vlastnost boundingRect a metodu draw(in:). Díky protokolu lze jakýkoli tvar implementující Drawable zpracovávat jednotně — to je polymorfismus bez dědičnosti od společné základní třídy.
Protocol-Oriented Programming (POP) — paradigma navržené Apple na WWDC 2015 jako alternativa k třídní dědičnosti. V POP jsou protokoly hlavním nástrojem abstrakce a rozšíření protokolů (protocol extensions) poskytují výchozí implementaci. To řeší problém «kosočtverečné dědičnosti» a umožňuje rozšiřovat existující typy bez úpravy zdrojového kódu.
| Aspekt | POP (Protocol-Oriented) | OOP (Class-based) |
|---|---|---|
| Jednotka abstrakce | Protocol | Základní třída |
| Opětovné použití | Protocol extension | Dědičnost |
| Value types | Podporovány (struct) | Pouze reference types |
| Vícenásobné použití | Protocol composition | Vícenásobná dědičnost (ne ve Swift) |
| Riziko provázanosti | Nízké (volná vazba) | Vysoké (strnulá hierarchie) |
Podle blogu Apple Swift (2025) tvoří struktury 70 % typů v moderních aplikacích Swift. POP je hlavním důvodem tohoto posunu: protokoly umožňují strukturám získat polymorfní chování bez přechodu na třídy.
Swift protokoly zaujímají střední pozici mezi rozhraními Java a abstraktními třídami C++. Mohou obsahovat implementaci (přes extension), ale nemají stav (uložené vlastnosti). Podívejme se na rozdíly na příkladu tří jazyků.
| Vlastnost | Swift Protocol | Java Interface | C++ Abstract Class |
|---|---|---|---|
| Implementace metod | Ano (extension) | Ano (default methods) | Ano |
| Uložené vlastnosti | Ne | Ne | Ano |
| Value types | Ano | Ne | Ne |
| Vícenásobná implementace | Ano | Ano | Ano |
| Inicializátory | Ano (požadavky) | Ne | Ano |
Klíčový rozdíl: Swift Protocol může vyžadovat inicializátory a subscript, což není dostupné v Java Interface. Protokol však nemůže uchovávat stav — to zůstává výsadou typu, který protokol implementuje.
Associated Type (přidružený typ) — zobecněný typ uvnitř protokolu, který je konkretizován implementujícím typem. To umožňuje vytvářet typově bezpečné protokoly bez určení konkrétního datového typu. Přidružené typy pracují společně s generiky Swift.
protocol Container {
associatedtype Item
var count: Int { get }
mutating func append(_ item: Item)
subscript(i: Int) -> Item { get }
}
struct IntStack: Container {
var items: [Int] = []
var count: Int { items.count }
typealias Item = Int
mutating func append(_ item: Int) {
items.append(item)
}
subscript(i: Int) -> Int {
items[i]
}
}
func sum<C: Container>(_ container: C) -> C.Item where C.Item: Numeric {
// tělo funkce
}Container — protokol s associatedtype Item. IntStack jej implementuje a určuje typealias Item = Int. Generická funkce sum používá where-omezení pro práci pouze s numerickými kontejnery. Associated types činí protokoly zobecněnými bez ztráty typové bezpečnosti.
Protocol composition — kombinování více protokolů pomocí operátoru &. Typ odpovídající kompozici musí implementovat všechny spojené protokoly. To nahrazuje vícenásobnou dědičnost, která ve Swift chybí, a umožňuje přesně specifikovat požadavky na parametry funkce.
protocol Named { var name: String { get } }
protocol Aged { var age: Int { get } }
struct Person: Named, Aged {
let name: String
let age: Int
}
func greet(_ entity: Named & Aged) {
print("Ahoj, \(entity.name), věk \(entity.age)!")
}
// Protocol extension — výchozí implementace
extension Named {
func introduce() {
print("Jmenuji se \(name)")
}
}Protocol extension poskytuje výchozí implementaci metod. Typ implementující protokol může přepsat metodu extension — v tom případě je volána jeho vlastní implementace. To je mechanismus, kterým Swift implementuje volitelné metody bez @objc.
@protocol v Objective-C — předchůdce Swift Protocol, ale s významnými omezeními. Objective-C protokoly jsou dostupné pouze pro třídy (ne pro struktury nebo výčty) a používají dynamické odesílání prostřednictvím message passing. Metody mohou být @required (výchozí) nebo @optional.
@protocol Loggable
@required
- (void)logMessage: (NSString *)message;
@optional
- (NSString *)logPrefix;
@end
@interface ConsoleLogger : NSObject
@end
@implementation ConsoleLogger
- (void)logMessage: (NSString *)message {
NSLog(@"[LOG] %@", message);
}
@endNa rozdíl od Swift, Objective-C protokoly nepodporují associated types, generics, protocol extensions a value types. Zůstávají mechanismem třídní abstrakce, zatímco Swift Protocol je plnohodnotný nástroj polymorfismu pro všechny typy.
Často kladené dotazy
Protocol nemůže uchovávat stav (uložené vlastnosti) — pouze požadavky na vlastnosti. Abstract class může obsahovat pole s daty. Protocol může být implementován strukturami a výčty, abstract class — pouze třídami. Ve Swift jsou protokoly hlavním nástrojem abstrakce, třídy se používají méně často.
POP — paradigma, kde protokoly a rozšíření protokolů nahrazují hluboké hierarchie dědičnosti. Místo základní třídy, ze které dědí všechny podtřídy, POP používá kompozici protokolů s výchozími implementacemi přes extension. To snižuje provázanost a zvyšuje znovupoužitelnost kódu.
Ano, Swift protokoly podporují dědičnost. protocol SerializableDrawable: Drawable, Codable — protokol spojující požadavky Drawable a Codable. Typ implementující SerializableDrawable musí splnit požadavky všech protokolů v hierarchii. To se liší od třídní dědičnosti — protokoly nemají společného předka.
some (opaque type) zaručuje, že funkce vrací jeden konkrétní typ odpovídající protokolu. any (existential type) umožňuje ukládat jakýkoli typ odpovídající protokolu. some se používá pro zachování identity typu, any — pro heterogenní kolekce. some se objevilo ve Swift 5.1, any — ve Swift 5.7.
Použijte is pro kontrolu a as? pro převod: if let drawable = object as? Drawable { drawable.draw(in: ctx) }. V Objective-C se používá conformsToProtocol:. Swift také podporuje is-kontrolu pro protokoly bez associated types.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také