Geschiedenis van de vraag:
In Swift tot versie 5 stuitte men bij het teruggeven van een waarde die overeenkomt met een protocol met associated type vaak op beperkingen — het type kon niet rechtstreeks als return type worden gebruikt, type erasure was nodig. Om de leesbaarheid en prestaties te verbeteren, zijn opaque types geïntroduceerd — teruggegeven waarden via het sleutelwoord some, waarmee abstracties in publieke interfaces kunnen worden beschreven.
Probleem:
Wanneer het nodig is om het echte type van het teruggegeven resultaat te verbergen, terwijl de abstractie via een protocol behouden blijft, maar tegelijkertijd de kosten van dynamic dispatch en type erasure te vermijden. Bijvoorbeeld, bij het teruggeven van collecties, sequenties, view-componenten.
Oplossing:
Opaque types maken het mogelijk om een type dat aan een protocol voldoet terug te geven, waarbij de specifieke implementatie ervan verborgen blijft. De compiler kent het echte type, maar de aanroepende zijde niet.
Voorbeeld:
protocol Shape { func area() -> Double } struct Circle: Shape { var radius: Double func area() -> Double { Double.pi * radius * radius } } func makeCircle() -> some Shape { return Circle(radius: 3) } let s = makeCircle() print(s.area()) // werkt
Belangrijke kenmerken:
someHoe verschilt opaque type (some Protocol) van het geretourneerde type Protocol?
Opaque type heeft bij compilatie een specifieke implementatie (hoewel deze van buitenaf verborgen is). Bij het retourneren van Protocol werkt dynamic dispatch, is er geen type safety als er associated types zijn.
Kan ik verschillende types retourneren met behulp van some Protocol in één functie?
Nee. Alle return-statements moeten hetzelfde echte type retourneren:
func maker(flag: Bool) -> some Shape { if flag { return Circle(radius: 3) } else { return Square(size: 2) // Fout: return type komt niet overeen } }
Kan associatedtype binnen een Protocol worden gebruikt via some Protocol?
Ja. Dit is precies waarvoor (voornamelijk) opaque type nodig is:
protocol View { associatedtype Body } func makeView() -> some View { /* ... */ }
De functie retourneert protocol zonder opaque, wat het gebruik van methoden met associatedtype niet toestaat, complexe type erasure vereist, waardoor de code niet compileert of niet optimaal werkt.
Voordelen:
Nadelen:
ViewBuilder in SwiftUI gebruikt some View, verbergt de details, verbetert type veiligheid, verhoogt compilatiesnelheid en runtime.
Voordelen:
Nadelen: