Swift Academy · Lekcja

Implementacje domyślne w rozszerzeniach

Udostępnianie wspólnego zachowania za pomocą rozszerzeń protokołów.

Lekcja 2 z 413 kroki

Implementacje domyślne w rozszerzeniach to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 4 lekcji w sumie.

Problem

Protokoły deklarują wymagania, ale nie zapewniają zachowania. Gdyby każdy typ zgodny z protokołem musiał powtarzać tę samą logikę, kod byłby zduplikowany. Rozszerzenia protokołów rozwiązują ten problem, dostarczając implementacje domyślne.

protocol Greeter {
    func greet() -> String
}

Dodawanie implementacji domyślnej

Rozszerzenie protokołu może implementować wymaganie. Typy zgodne z protokołem otrzymują to zachowanie automatycznie, chyba że je zastąpią własną implementacją.

protocol Greeter { func greet() -> String }

extension Greeter {
    func greet() -> String { "Hello!" }
}

struct Robot: Greeter {}
print(Robot().greet())

Zastępowanie implementacji domyślnej

Typ zgodny z protokołem może dostarczyć własną implementację, która ma pierwszeństwo przed implementacją domyślną z rozszerzenia.

protocol Greeter { func greet() -> String }
extension Greeter { func greet() -> String { "Hello!" } }

struct French: Greeter {
    func greet() -> String { "Bonjour!" }
}
print(French().greet())

Dodawanie dodatkowych metod

Rozszerzenia mogą dodawać zupełnie nowe metody, których w ogóle nie ma w protokole. Każdy typ zgodny z protokołem otrzymuje je automatycznie.

protocol Named { var name: String { get } }

extension Named {
    func loudName() -> String { name.uppercased() }
}

struct City: Named { let name: String }
print(City(name: "paris").loudName())

Domyślne właściwości obliczane

Rozszerzenia mogą również dostarczać domyślne właściwości obliczane.

protocol Sized {
    var width: Double { get }
    var height: Double { get }
}

extension Sized {
    var area: Double { width * height }
}

struct Rect: Sized { let width: Double; let height: Double }
print(Rect(width: 2, height: 5).area)

Budowanie na podstawie wymagań

Implementacja domyślna może wywoływać własne wymagania protokołu, tworząc bogatsze zachowanie z minimalnego kontraktu, który musi spełnić każdy typ.

protocol Summable {
    var values: [Int] { get }
}

extension Summable {
    var total: Int { values.reduce(0, +) }
}

struct Cart: Summable { let values: [Int] }
print(Cart(values: [10, 20, 30]).total)

Rozszerzenia z ograniczeniami

Użyjcie klauzuli where, aby implementacja domyślna obowiązywała tylko wtedy, gdy są spełnione dodatkowe warunki. W tym przypadku implementacja domyślna istnieje tylko wtedy, gdy Self jest również zgodny z Equatable.

protocol Container {
    associatedtype Item
    var items: [Item] { get }
}

extension Container where Item: Equatable {
    func contains(_ x: Item) -> Bool { items.contains(x) }
}

struct Bag: Container { let items: [Int] }
print(Bag(items: [1, 2, 3]).contains(2))

Implementacja domyślna i wymaganie razem

Możecie zadeklarować metodę w protokole ORAZ dostarczyć jej implementację domyślną. Umieszczenie metody w protokole umożliwia dynamiczne wysyłanie wywołań za pośrednictwem typu protokołu.

protocol Logger {
    func log() -> String
}
extension Logger {
    func log() -> String { "default log" }
}

struct A: Logger {}
struct B: Logger { func log() -> String { "B log" } }

let loggers: [Logger] = [A(), B()]
for l in loggers { print(l.log()) }

Pułapka statycznego wysyłania

Jeśli metoda znajduje się WYŁĄCZNIE w rozszerzeniu, a nie w protokole, wywołania za pośrednictwem wartości typowanej jako protokół używają wersji z rozszerzenia, nawet jeśli konkretny typ definiuje własną wersję. Zadeklarujcie metodę w protokole, aby używać dynamicznego wysyłania.

protocol P {}
extension P { func who() -> String { "P-default" } }
struct Q: P { func who() -> String { "Q" } }

let direct = Q()
let asP: P = Q()
print(direct.who())
print(asP.who())

Ograniczanie powtarzalnego kodu

Połączenie niewielkiego zbioru wymagań z bogatymi implementacjami domyślnymi stanowi istotę projektowania zorientowanego protokołowo: typy zgodne z protokołem implementują minimum, a wspólne zachowanie znajduje się w jednym miejscu.

protocol Identifiable { var id: Int { get } }
extension Identifiable {
    var tag: String { "ID-" + String(id) }
}
struct Order: Identifiable { let id: Int }
print(Order(id: 7).tag)

Łączenie wielu rozszerzeń

Możecie podzielić implementacje domyślne na kilka rozszerzeń, aby uporządkować kod; wszystkie one wzbogacają typ zgodny z protokołem.

protocol Money { var cents: Int { get } }
extension Money { var dollars: Double { Double(cents) / 100 } }
extension Money { var label: String { "$" + String(format: "%.2f", dollars) } }

struct Price: Money { let cents: Int }
print(Price(cents: 1299).label)

Szybkie sprawdzenie

Sprawdźcie swoją znajomość implementacji domyślnych w rozszerzeniach protokołów.

Podsumowanie

Rozszerzenia protokołów dostarczają implementacji domyślnych, dzięki czemu typy zgodne z protokołem mogą dziedziczyć wspólne zachowanie i zastępować je w razie potrzeby. Możecie dodawać dodatkowe metody i właściwości obliczane, ograniczać implementacje domyślne za pomocą where oraz znacie zasadę statycznego i dynamicznego wysyłania: zadeklarujcie metodę w protokole, aby używać dynamicznego wysyłania.

Bezpłatny start

Ucz się Swift dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
122
Lekcje
409

Często zadawane pytania

Czy lekcja „Implementacje domyślne w rozszerzeniach” jest bezpłatna?

Tak — pełny tekst „Implementacje domyślne w rozszerzeniach” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Implementacje domyślne w rozszerzeniach”?

Udostępnianie wspólnego zachowania za pomocą rozszerzeń protokołów. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Swift Academy?

Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Implementacje domyślne w rozszerzeniach”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?

Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Protokoły jako kontrakty
  2. Implementacje domyślne w rozszerzeniach
  3. Kompozycja protokołów
  4. Warunkowa zgodność
← Powrót do Swift Academy