Protocol — co to jest, protokoły i delegaty w iOS

Autor: IT Sectr Opublikowano: 2026-02-18 Czas czytania: 10 min

Protocol — to zestaw wymagań (właściwości i metody), którym musi odpowiadać typ implementujący dany protokół. W Swift protokoły są centralnym elementem Protocol-Oriented Programming (POP), umożliwiającym polimorfizm bez dziedziczenia. Według danych Swift.org (2025), protokoły są używane w 85% typów standardowej biblioteki Swift. W Objective-C @protocol pełni podobną rolę, ale z ograniczeniem — tylko dla klas.

Najważniejsze

  • Protocol — kontrakt określający interfejs, który musi zaimplementować struktura, klasa lub wyliczenie
  • Protocol-Oriented Programming — paradygmat Swift, w którym protokoły i rozszerzenia protokołów zastępują głęboką hierarchię dziedziczenia
  • Protocol extension — domyślna implementacja metod, czyniąca metody protokołu opcjonalnymi bez @objc
  • Associated types — uogólnione protokoły z powiązanymi typami dla bezpiecznego typowo działania z różnymi typami danych
  • Protocol composition — łączenie wielu protokołów za pomocą operatora & w celu precyzyjnego opisu wymagań

Czym jest protokół w Swift?

Protocol w Swift — to abstrakcyjny interfejs określający wymagania, którym musi odpowiadać typ. Protokół może wymagać właściwości (z getterem/setterem), metod (instancji i typu), inicjalizatorów oraz subscript. W przeciwieństwie do klas, protokoły mogą być implementowane przez struktury, wyliczenia i klasy — daje to elastyczność niedostępną w czysto klasowych językach.

Swift
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 protokół Drawable, udostępniając właściwość boundingRect oraz metodę draw(in:). Dzięki protokołowi dowolną figurę implementującą Drawable można przetwarzać jednolicie — to polimorfizm bez dziedziczenia od wspólnej klasy bazowej.

Protocol-Oriented Programming: paradygmat Swift

Protocol-Oriented Programming (POP) — paradygmat zaproponowany przez Apple na WWDC 2015 jako alternatywa dla dziedziczenia klasowego. W POP protokoły są głównym narzędziem abstrakcji, a rozszerzenia protokołów (protocol extensions) dostarczają domyślnych implementacji. Rozwiązuje to problem „dziedziczenia rombowego” i pozwala rozszerzać istniejące typy bez modyfikacji kodu źródłowego.

AspektPOP (Protocol-Oriented)OOP (Class-based)
Jednostka abstrakcjiProtocolKlasa bazowa
Ponowne użycieProtocol extensionDziedziczenie
Value typesWspierane (struct)Tylko reference types
Wielokrotne zastosowanieProtocol compositionDziedziczenie wielokrotne (nie w Swift)
Ryzyko sprzężeniaNiskie (słabe powiązanie)Wysokie (sztywna hierarchia)

Według danych Apple Swift blog (2025), struktury stanowią 70% typów we współczesnych aplikacjach Swift. POP — kluczowy powód tego przesunięcia: protokoły umożliwiają strukturom uzyskanie polimorficznego zachowania bez przechodzenia na klasy.

Protocol vs abstract class vs interface

Protokoły Swift zajmują pozycję pośrednią między interfejsami Java a abstrakcyjnymi klasami C++. Mogą zawierać implementację (przez extension), ale nie mają stanu (przechowywanych właściwości). Omówimy różnice na przykładzie trzech języków.

CechaSwift ProtocolJava InterfaceC++ Abstract Class
Implementacja metodTak (extension)Tak (default methods)Tak
Przechowywane właściwościNieNieTak
Value typesTakNieNie
Wielokrotna implementacjaTakTakTak
InicjalizatoryTak (wymagania)NieTak

Kluczowa różnica: Swift Protocol może wymagać inicjalizatorów i subscript, co jest niedostępne w Java Interface. Protokół nie może jednak przechowywać stanu — pozostaje to domeną typu implementującego protokół.

Associated Types i Generics w protokołach

Associated Type (typ powiązany) — to uogólniony typ wewnątrz protokołu, który jest konkretyzowany przez implementujący typ. Pozwala to tworzyć bezpieczne typowo protokoły bez określania konkretnego typu danych. Typy powiązane działają w parze z generykami Swift.

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 {
    // ciało funkcji
}

Container — protokół z associatedtype Item. IntStack implementuje go, określając typealias Item = Int. Funkcja generyczna sum używa where-ograniczenia do działania tylko z kontenerami numerycznymi. Associated types czynią protokoły uogólnionymi bez utraty bezpieczeństwa typowego.

Protocol composition i rozszerzenia protokołów

Protocol composition — łączenie wielu protokołów za pomocą operatora &. Typ odpowiadający kompozycji musi zaimplementować wszystkie połączone protokoły. Zastępuje to wielokrotne dziedziczenie, nieobecne w Swift, i pozwala precyzyjnie określać wymagania dla parametrów funkcji.

Swift
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("Witaj, \(entity.name), wiek \(entity.age)!")
}

// Protocol extension — domyślna implementacja
extension Named {
    func introduce() {
        print("Nazywam się \(name)")
    }
}

Protocol extension dostarcza domyślną implementację metod. Typ implementujący protokół może nadpisać metodę extension — wtedy wywoływana jest jego własna implementacja. To mechanizm, za pomocą którego Swift realizuje opcjonalne metody bez @objc.

@protocol w Objective-C: różnice od Swift

@protocol w Objective-C — poprzednik Swift Protocol, ale z istotnymi ograniczeniami. Protokoły Objective-C są dostępne tylko dla klas (nie dla struktur ani wyliczeń) i używają dynamicznego wysyłania przez message passing. Metody mogą być @required (domyślnie) lub @optional.

Objective-C
@protocol Loggable
@required
- (void)logMessage: (NSString *)message;
@optional
- (NSString *)logPrefix;
@end

@interface ConsoleLogger : NSObject 
@end

@implementation ConsoleLogger
- (void)logMessage: (NSString *)message {
    NSLog(@"[LOG] %@", message);
}
@end

W przeciwieństwie do Swift, protokoły Objective-C nie wspierają associated types, generics, protocol extensions ani value types. Pozostają mechanizmem abstrakcji klasowej, podczas gdy Swift Protocol jest pełnoprawnym narzędziem polimorfizmu dla wszystkich typów.

Często zadawane pytania

Czym różni się protokół od klasy abstrakcyjnej?

Protocol nie może przechowywać stanu (przechowywanych właściwości) — tylko wymagania dotyczące właściwości. Abstract class może zawierać pola z danymi. Protocol może być implementowany przez struktury i wyliczenia, abstract class — tylko przez klasy. W Swift protokoły są głównym narzędziem abstrakcji, klasy są używane rzadziej.

Czym jest Protocol-Oriented Programming?

POP — paradygmat, w którym protokoły i rozszerzenia protokołów zastępują głębokie hierarchie dziedziczenia. Zamiast klasy bazowej, od której dziedziczą wszystkie podklasy, POP używa kompozycji protokołów z domyślnymi implementacjami przez extension. Zmniejsza to powiązanie i zwiększa ponowne użycie kodu.

Czy protokół może dziedziczyć inny protokół?

Tak, protokoły Swift wspierają dziedziczenie. protocol SerializableDrawable: Drawable, Codable — protokół łączący wymagania Drawable i Codable. Typ implementujący SerializableDrawable musi spełnić wymagania wszystkich protokołów w hierarchii. Różni się to od dziedziczenia klas — protokoły nie mają wspólnego przodka.

Czym są any i some w kontekście protokołów?

some (opaque type) gwarantuje, że funkcja zwraca jeden konkretny typ odpowiadający protokołowi. any (existential type) pozwala przechowywać dowolny typ odpowiadający protokołowi. some jest używane do zachowania tożsamości typu, any — do kolekcji heterogenicznych. some pojawiło się w Swift 5.1, any — w Swift 5.7.

Jak sprawdzić zgodność z protokołem w Swift?

Użyj is do sprawdzenia i as? do rzutowania: if let drawable = object as? Drawable { drawable.draw(in: ctx) }. W Objective-C używa się conformsToProtocol:. Swift obsługuje również is-sprawdzenie dla protokołów bez associated types.

Podsumowanie

  • Protocol — kontrakt określający wymagania dotyczące właściwości, metod, inicjalizatorów i subscript dla implementującego typu
  • Protocol-Oriented Programming zastępuje dziedziczenie klasowe kompozycją protokołów z rozszerzeniami
  • Protocol extension dostarcza domyślną implementację, czyniąc metody opcjonalnymi bez @objc
  • Associated types umożliwiają tworzenie uogólnionych protokołów z konkretyzacją typu po stronie implementacji
  • Protocol composition przez & łączy wymagania wielu protokołów
  • Objective-C @protocol jest ograniczony do klas i nie wspiera associated types, generics ani value types
  • Zalecenie: używaj protokołów jako głównego narzędzia abstrakcji w Swift, stosując klasy tylko gdy konieczna jest semantyka referencyjna

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również