ProgrammatieiOS ontwikkelaar, Middle/Senior

Wat zijn opaque types (some) in Swift, waarom zijn ze nodig en wanneer moet je ze toepassen in plaats van protocol types?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Geschiedenis van de vraag: Opaque types (some) kwamen naar voren in Swift 5.1 en introduceerden een nieuwe manier om het retourtype van een functie of eigenschap te abstraheren, wanneer het type bekend is voor de compiler, maar verborgen blijft voor de gebruiker. Dit is een alternatief voor protocol existentials (any Protocol), maar met een strikte binding aan een specifiek type binnen de functie.

Probleem: Wanneer een functie een protocol met associatedtype retourneert (bijvoorbeeld, Sequence), kan je niet direct schrijven:

func makeNumberSequence() -> Sequence { ... } // fout

Protocol existentials stellen je in staat om elke implementatie te retourneren, maar garanderen niet hetzelfde type bij elke oproep:

func foo() -> any View { ... }

Dit leidt tot onvoorspelbaarheid en zwakke type veiligheid.

Oplossing: Gebruik opaque result type:

func makeNumbers() -> some Sequence { [1, 2, 3] }

Nu weet de compiler precies welk type er daadwerkelijk wordt geretourneerd, maar dit blijft verborgen voor buitenstaanders. Dit biedt prestatieoptimalisaties, veiligheid, stelt je in staat om SwiftUI DSL te gebruiken, en vergemakkelijkt het type-uitwisselen tussen modules.

Belangrijkste kenmerken:

  • Het specifieke type binnen het opaque type is altijd één
  • Ondersteunt geen associatedtype op gebruiksplek, maar wel in definitie
  • Gebruikt voor het bouwen van declaratieve API's (bijvoorbeeld SwiftUI)

Vragen met een valstrik.

Kunnen opaque types worden gebruikt om waarden op te slaan (zoals class properties)?

Nee. Opaque types worden alleen toegepast voor retourwaarden van functies of computed properties. Voor opslaan van waarden of arrays van waarden gebruik je existentials (any Protocol).

Kunnen verschillende takken van één functie verschillende types met some retourneren?

Nee. De compiler vereist dat beide (of alle) takken hetzelfde specifieke type retourneren, anders krijg je een fout:

func foo(flag: Bool) -> some Sequence { if flag { return [1, 2, 3] } else { return ["a", "b", "c"] // fout } }

Kan some worden gebruikt om het retourtype tussen meerdere functies te identificeren?

Nee. Elke functie met some retourneert haar unieke verborgen type, zelfs als dit feitelijk dezelfde array is. Het gebruik van de retourwaarde van één functie als parameter in een andere is niet toegestaan als beide some gebruiken met verschillende protocollen of verschillende verborgen types.

Typische fouten en antipatterns

  • Proberen verschillende types terug te geven via some (compilatiefout)
  • some gebruiken waar protocol existentials vereist zijn (bijvoorbeeld voor het opslaan van staten)
  • Optimalisaties missen door old-style protocol types te blijven gebruiken

Voorbeeld uit het leven

Negatief geval

In een project wordt alles geretourneerd via any Protocol, collecties verliezen type-informatie, er ontstaan bugs bij downcasting, compile-tijd optimalisatie vertraagt.

Voordelen:

  • Flexibele architectuur met de mogelijkheid om verschillende types te combineren

Nadelen:

  • Verlies van type veiligheid, vermindering van efficiëntie, problemen met casting

Positief geval

In SwiftUI-ontwerp retourneren componenten some View, elk module definieert duidelijk het interne type. De bundelgrootte wordt verkleind, de build wordt versneld.

Voordelen:

  • Verbeterde prestaties, toename van type veiligheid

Nadelen:

  • Bepaalde verlies van flexibiliteit wanneer dynamische opslag nodig is