Protocol Extension — mechanismus Swiftu, který umožňuje poskytnout výchozí implementaci metod a vlastností pro protokol. V kombinaci s omezeními where umožňuje protocol extension přidávat chování pouze těm typům, které splňují určité podmínky. Podle Apple Documentation, 2026 se jedná o klíčový prvek protokolově orientovaného programování, který umožňuje znovupoužití kódu bez hierarchie tříd.
Hlavní
Protocol Extension — je způsob, jak přidat implementaci metod a vypočítávaných vlastností k existujícímu protokolu. Bez extensions protokol definuje pouze požadavky a každý typ je implementuje samostatně.
Protocol Extension řeší problém duplicity kódu: pokud pět struktur přijme stejný protokol a implementuje stejnou metodu, extension poskytuje výchozí implementaci jednou.
Podle Swift Evolution proposal SE-0186 jsou protocol extensions jednou z klíčových funkcí, které předurčily úspěch POP. Umožňují přidávat společné chování bez vytváření základních tříd a bez porušení principu jedné odpovědnosti.
Protocol Extension se deklaruje jako běžný extension, ale s názvem protokolu místo typu.
protocol Greetable {
var name: String { get }
func greet() -> String
}
extension Greetable {
func greet() -> String {
return "Hello, \(name)!"
}
}
Nyní každý typ, který přijme Greetable, automaticky získá implementaci greet:
struct Person: Greetable {
let name: String
}
// Person má automaticky greet()
let user = Person(name: "Alice")
print(user.greet()) // „Hello, Alice!“
Protocol Extension může obsahovat vypočítávané vlastnosti, ale ne stored properties (protokoly nemohou definovat úložiště). Můžete také přidat subscripts a vnořené typy prostřednictvím extension.
Default implementation — hlavní použití protocol extension. Typ může metodu přepsat tím, že poskytne vlastní verzi.
protocol Loggable {
func log(message: String)
}
extension Loggable {
func log(message: String) {
print("[Default] \(message)")
}
}
struct ConsoleLogger: Loggable {}
// Používá výchozí implementaci
struct FileLogger: Loggable {
func log(message: String) {
// Vlastní implementace přepisuje výchozí
writeToFile(message)
}
}
Důležitý rozdíl oproti dědicnosti tříd: pokud typ sám implementuje metodu protokolu, je volána jeho implementace. Pokud ne — je použita výchozí z extension. Jedná se o statický dispatch, rozhodnutí se přijímá při kompilaci.
Where clause umožňuje omezit protocol extension pouze na ty typy, které splňují další podmínky. Jedná se o mocný mechanismus pro přidávání specializovaného chování.
protocol Printable {
var content: String { get }
}
extension Printable where Self: CustomStringConvertible {
func debugPrint() -> String {
return "[Printable] \(content)"
}
}
Zde je debugPrint k dispozici pouze typům, které současně implementují Printable a CustomStringConvertible. Standardní knihovna Swiftu tento vzor hojně využívá — například extension pro Collection where Element.
Obzvláště užitečné jsou where clauses s omezením rovnosti typu:
extension Collection where Element == String {
func commaJoined() -> String {
return self.joined(separator: ", ")
}
}
let words = ["Swift", "Kotlin", "Java"]
print(words.commaJoined()) // „Swift, Kotlin, Java“
Tento mechanismus činí protocol extension selektivním: metoda commaJoined je k dispozici pouze pro kolekce řetězců, ale ne pro číselné kolekce. Kompilátor kontroluje omezení staticky.
Where constraints mohou kontrolovat:
where Self: Equatablewhere Element == Stringwhere Element: Numeric, Element: ComparableTo činí z protocol extension mocný mechanismus pro přidávání specializovaného chování bez znečištění obecné implementace protokolu.
Mnoho vývojářů si klade otázku: kdy používat protocol extensions a kdy — dědicnost tříd? Odpověď závisí na architektonickém paradigmatu.
| Charakteristika | Protocol Extension | Dědicnost tříd |
|---|---|---|
| Value types | Funguje s struct a enum | Pouze třídy |
| Vícenásobné použití | Typ může přijmout mnoho protokolů | Jedna nadtřída |
| Stav | Žádné stored properties | Může mít stored properties |
| Dispatch | Static dispatch (výchozí) | Dynamic dispatch (virtuální tabulky) |
Apple doporučuje začít s protocol + extension a přejít na třídy pouze tehdy, když je potřeba sdílený stav nebo identita (reference semantics). Protocol extensions poskytují kompozici místo dědicnosti — flexibilnější a lépe testovatelný přístup.
V praxi jsou protocol extensions často používány k přidávání pohodlných obalových metod nad požadavky protokolu. Například, pokud protokol vyžaduje metodu validate s podrobnou zprávou, extension může přidat metodu isValid, která vrací booleovskou hodnotu na základě plné verze. To zjednodušuje klientský kód, aniž by se měnila smlouva protokolu. Tento vzor se nazývá «default implementation s derived API» a je široce používán ve standardní knihovně Swiftu a populárních frameworkových třetích stran. Jedná se o jednu z klíčových technik protokolově orientovaného programování v akci a základ flexibilní architektury.
Často kladené otázky
Ne, protocol extension může obsahovat pouze vypočítávané vlastnosti. Stored properties jsou zakázány, protože protokol nevlastní paměť — konkrétní typ (struct, class, enum) je odpovědný za ukládání dat.
Používá se statický dispatch: pokud typ explicitně implementuje metodu — je volána jeho verze. Pokud ne — výchozí z extension. Při přístupu přes existential (any) se používá dynamic dispatch.
Ano, protocol extension může obsahovat inicializátory. Protokol však nemůže vyžadovat init prostřednictvím extension — požadavek musí být v deklaraci protokolu a implementace v typu.
Protocol extension se aplikuje na všechny typy, které přijaly protokol. Extension pro typ — pouze na jeden konkrétní typ. Protocol extension poskytuje polymorfismus bez dědicnosti.
Ne, Swift zakazuje vnořené protocol extensions. Každý protocol extension se deklaruje na úrovni souboru. Pro organizaci kódu používejte značky // MARK: a samostatné soubory.
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é