Extension w Swift to mechanizm umożliwiający dodanie nowej funkcjonalności do istniejących typów bez modyfikacji ich kodu źródłowego. Rozszerzenia obsługują metody, właściwości obliczane, inicjalizatory, subskrypty, typy zagnieżdżone i implementację protokołów. Według Apple Documentation, 2026, rozszerzenia to kluczowe narzędzie do organizacji kodu i przestrzegania zasady Open/Closed Principle w projektach Swift.
Najważniejsze
Extension w Swift to konstrukcja językowa umożliwiająca rozszerzenie istniejącego typu (klasy, struktury, enum, protokołu) o nowe możliwości. To odpowiednik kategorii w Objective-C, ale z większymi możliwościami.
Extension może dodawać:
Według dokumentacji Apple, extension nie może nadpisywać istniejących metod (dynamic dispatch) ani dodawać stored properties. Te ograniczenia zachowują integralność oryginalnego typu.
Extension deklaruje się za pomocą słowa kluczowego extension z podaniem rozszerzanego typu.
extension Double {
var km: Double { return self * 1000.0 }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1000.0 }
}
let distance = 5.0.km
print("5 km = \(distance) metrów") // 5000.0
Rozszerzać można nie tylko własne typy, ale także typy biblioteki standardowej Swift, Foundation, UIKit i innych frameworków. To czyni extension potężnym narzędziem do dodawania funkcjonalności specyficznej dla domeny.
Extension umożliwia dodawanie metod instancji i typu do dowolnego istniejącego typu.
extension String {
func isValidEmail() -> Bool {
let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
return self.range(of: emailRegex, options: .regularExpression) != nil
}
static func random(length: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyz0123456789"
return String((0..<length).map { _ in letters.randomElement()! })
}
}
let email = "user@example.com"
print(email.isValidEmail()) // true
let code = String.random(length: 8) // "a3f8k2m1"
Metody mutujące rozszerzają typy wartościowe (struct, enum) i mogą modyfikować self. Dla klas mutowanie nie jest wymagane. Extension może dodawać metody mutujące nawet do typów biblioteki standardowej.
Extension może dodawać tylko właściwości obliczane — stored properties są zabronione. Jest to logiczne: extension nie zarządza pamięcią oryginalnego typu.
extension Date {
var isPast: Bool {
return self < Date()
}
var isToday: Bool {
return Calendar.current.isDateInToday(self)
}
}
let someDate = Date().addingTimeInterval(3600)
print(someDate.isPast) // false (godzina od teraz to przyszłość)
Computed properties w extension podlegają tym samym zasadom co w podstawowej implementacji: można tworzyć właściwości { get } i { get set }. Swift nie nakłada ograniczeń na liczbę extension dla jednego typu. Możesz zadeklarować dowolnie wiele extension dla jednego typu w różnych plikach — to standardowa praktyka w dużych projektach.
Extension to preferowany sposób implementacji protokołów. Zamiast zaśmiecać podstawową deklarację typu, wszystkie metody protokołu są wyodrębniane w osobny extension.
struct User {
let id: Int
let name: String
let email: String
}
// Extension według protokołu — czyste rozdzielenie
extension User: Equatable {
static func == (lhs: User, rhs: User) -> Bool {
return lhs.id == rhs.id
}
}
extension User: Codable {
enum CodingKeys: String, CodingKey {
case id, name, email
}
}
Takie podejście dzieli odpowiedzialność: podstawowa struktura zawiera tylko stored properties, a extensions — implementację protokołów. Swift pozwala nawet na implementację protokołu przez extension dla typów, których nie kontrolujemy.
Extension to nie tylko możliwość językowa, ale narzędzie organizacji architektury. Prawidłowe użycie extensions sprawia, że kod jest czytelny i łatwy w utrzymaniu.
// MARK: - Equatable dla nawigacjiprivate// MARK: - User + Displayable
extension User: Displayable {
var displayName: String {
return "\(name) (\(email))"
}
}
Według Swift API Design Guidelines, extensions poprawiają czytelność: programista widzi strukturę danych w podstawowej deklaracji, a logikę — w extensions. Jest to zgodne z zasadą separacji interfejsu (Interface Segregation).
Extension z where-ograniczeniami dodaje metody tylko dla określonych typów: extension Array where Element: Equatable { func isUnique() -> Bool }. Taki kod jest zwięzły i bezpieczny typowo — metoda isUnique pojawia się tylko w tablicach z elementami Equatable, eliminując błędy na etapie kompilacji i czyniąc API czystszym, bezpieczniejszym i bardziej zrozumiałym dla innych programistów.
Często zadawane pytania
Nie, extension nie może dodawać stored properties. To ograniczenie jest fundamentalne: extension nie uczestniczy w alokacji pamięci dla instancji typu. Do stored properties używaj podstawowej deklaracji typu.
Nie, extension nie może nadpisywać metod. Próba zadeklarowania metody z tą samą sygnaturą co istniejąca spowoduje błąd kompilacji. Do nadpisywania używaj dziedziczenia klas.
Extension dodaje funkcjonalność bez tworzenia nowego typu. Subclassing tworzy hierarchię i obsługuje nadpisywanie. Extension nie wymaga dostępu do kodu źródłowego i działa ze wszystkimi typami.
Tak, extension może być generic, jeśli rozszerzany typ jest generic: extension Array where Element: Numeric. Można również dodać metody generic wewnątrz extension z własnymi parametrami typu.
Extension nie wpływa na wydajność — metody extension są kompilowane jak zwykłe metody. Dla protokołów z extension używany jest static dispatch, co może być szybsze niż dynamic dispatch klas.
Podsumowanie
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.
Przeczytaj również