W Swift konstrukcje switch i enum są zrealizowane z potężnymi możliwościami dopasowywania wzorców i ścisłą typobezpieczeństwem, co odróżnia je od większości odpowiedników w innych językach.
W C i C++, a także w Objective-C, enumeracje są tylko zbiorem wartości całkowitych, a operatory switch porównują wartości w celu dopasowania. W Swift enumeracje (enum) są znacznie potężniejsze — wspierają wartości skojarzone, właściwości obliczeniowe i metody. Operator switch wspiera dopasowywanie wzorców, zabezpieczenie przed niepełnymi gałęziami oraz pracę z zakresem, krotkami, opcjonalnymi wartościami i wieloma innymi.
W tradycyjnych językach switch często prowadzi do błędów związanych z brakiem exhaustiveness (wyczerpującego rozpatrywania wszystkich przypadków), błędami typów oraz niemożnością bezpiecznego przechowywania dodatkowych danych w przypadkach enum. Prowadzi to do błędów na etapie wykonywania, a nie kompilacji.
W Swift switch wymaga pełnego przetworzenia wszystkich przypadków, jeśli enumeracja nie jest wyraźnie oznaczona jako @unknown default. Wartości skojarzone pozwalają elegancko przechowywać dodatkowe informacje w przypadkach enum. Przykład:
enum NetworkResult { case success(Int) case failure(String) } func handle(result: NetworkResult) { switch result { case .success(let code): print("Sukces z kodem: \(code)") case .failure(let error): print("Niepowodzenie z błędem: \(error)") } }
Kluczowe cechy:
Czy zawsze trzeba pisać default w switch dla enum?
Nie, jeśli wszystkie przypadki enumeracji są wyraźnie pokryte, default nie jest potrzebny. Co więcej, default nie jest zalecane bez konieczności — kompilator może nie ostrzec o nowych przypadkach enum przy ich dodawaniu.
Czy można używać fallthrough do automatycznego przechodzenia między przypadkami?
Tak, słowo kluczowe fallthrough jest dostępne, ale należy go używać ostrożnie. Nie przekazuje ono wartości skojarzonych, a takie przejścia nie są często spotykane w realnej praktyce Swift.
switch number { case 1: print("jeden") fallthrough case 2: print("lub dwa") default: print("inny") }
Czy enum w Swift może być porównany przez rawValue, jeśli ma wartości skojarzone?
Nie. Tylko enumeracje bez wartości skojarzonych i z wyraźnie podanym rawValue mogą być inicjowane i porównywane przez rawValue.
Programista dodał default-case do switch w enum NetworkResult, co spowodowało, że po dodaniu nowego przypadku logika przetwarzania nie została zaktualizowana, a program "cicho" działał niepoprawnie.
Zalety: Brak ostrzeżeń kompilatora przy dodawaniu przypadków.
Wady: Błędy ujawniają się w czasie działania aplikacji, logika nie jest aktualizowana automatycznie.
Pracownik zrezygnował z default w switch w enum, co pozwoliło kompilatorowi wykrywać brak przetwarzania nowych przypadków po ich dodaniu.
Zalety: Błędy są wykrywane na etapie kompilacji, zachowanie aplikacji staje się bardziej przewidywalne.
Wady: Przy dużej liczbie przypadków potrzebne jest więcej kodu, ale zyskujemy na niezawodności.