Pattern matching is een fundamenteel kenmerk van Swift dat de code veiliger en netter maakt. Historisch gezien is pattern matching ontwikkeld als een middel om expressiever en veiliger te werken met enums, vooral met geassocieerde waarden. In tegenstelling tot andere talen, stelt Swift je in staat om geneste waarden direct uit te pakken in if-, guard- en switch-uitdrukkingen.
Probleem: voor niet-standaard enums, vooral met geneste geassocieerde waarden, is het gemakkelijk om fouten te maken in de case-structuur of de beperkingen van de hoofd switch te onderschatten. Vaak is het ook niet duidelijk wat het verschil is tussen het gebruik van if case, guard case en klassieke switch.
Oplossing: gebruik verschillende benaderingen voor pattern matching afhankelijk van de scenario's, en bij complexe geneste structuren, geef duidelijk namen op en gebruik where.
Voorbeeldcode:
enum NetworkState { case success(User) case failure(Error, code: Int) case loading(progress: Double) } let state = NetworkState.failure(SomeError(), code: 401) if case let .failure(error, code) = state, code == 401 { print("Unauthorized: \(error)") } guard case .success(let user) = state else { return } print(user) switch state { case .success(let user): print("Welcome, \(user.name)") case .failure(let error, let code) where code == 404: print("Not Found: \(error)") case .failure(_, let code): print("Failure with code: \(code)") case .loading(let progress): print("Progress: \(progress)") }
Belangrijke kenmerken:
Wat gebeurt er als je niet alle case-enums in switch vermeldt?
Compilatiefout (als de enum non-optional is) of waarschuwing/eis voor default case als niet alle dekkingen zijn meegenomen. Voor Optionals is het genoeg om alleen .some en .none op te geven.
Is pattern matching mogelijk met geneste enums en geassocieerde waarden?
Ja. Maar de syntax wordt ingewikkelder. Voor geneste waarden kun je meerdere niveaus meteen uitpakken:
enum Outer { case inner(Inner) } enum Inner { case item(id: Int) } let e = Outer.inner(.item(id: 5)) if case let .inner(.item(id)) = e { print(id) }
Wat is het verschil tussen guard case en if case bij pattern matching?
guard case controleert de voorwaarde en voert de exit-blok (return, throw, break) uit bij falen. Gewoonlijk gebruikt voor vereisten: als er geen match is, gaan.
if case is een constructie die geschikt is voor eendelige conditionele handelaars zonder functie-uitgang.
Een ontwikkelaar gebruikt switch voor een enum met meerdere cases, maar dekt een nieuwe case niet. De code compileert, maar het nieuwe scenario wordt niet verwerkt en de applicatie crasht tijdens runtime.
Voordelen:
Nadelen:
Een ontwikkelaar dekt expliciet alle cases, gebruikt where voor lokale filteringen, en pakt geneste waarden uit via genest let.
Voordelen:
Nadelen: