Historia de la cuestión:
En Swift antes de la versión 5, al devolver un valor que correspondía a un protocolo con associated type, a menudo se enfrentaba a limitaciones: no se podía utilizar el tipo como return type directamente, se requería type erasure. Para mejorar la legibilidad y el rendimiento, se introdujeron los opaque types: valores devueltos mediante la palabra clave some, que permiten describir abstracciones en interfaces públicas.
Problema:
Cuando es necesario ocultar el tipo real del valor de retorno, manteniendo la abstracción a través de un protocolo, pero evitando los costos del dynamic dispatch y el type erasure. Por ejemplo, al devolver colecciones, secuencias, componentes de vista.
Solución:
Los opaque types permiten devolver un tipo que corresponde a un protocolo, ocultando su implementación concreta. El compilador conoce el tipo real, pero la parte que llama no.
Ejemplo:
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()) // funciona
Características clave:
some¿En qué se diferencia opaque type (some Protocol) de un tipo de retorno Protocol?
El opaque type tiene una implementación concreta durante la compilación (aunque está oculta desde fuera). Al devolver Protocol, se utiliza dynamic dispatch, no hay type safety si hay associated type.
¿Se pueden devolver diferentes tipos utilizando some Protocol en una misma función?
No. Todos los return deben devolver el mismo tipo real:
func maker(flag: Bool) -> some Shape { if flag { return Circle(radius: 3) } else { return Square(size: 2) // Error: tipo de retorno no coincide } }
¿Puede associatedtype dentro de Protocol ser utilizado a través de some Protocol?
Sí. Esa es precisamente la razón por la que se necesita un opaque type:
protocol View { associatedtype Body } func makeView() -> some View { /* ... */ }
La función devuelve un protocolo sin opaque, no permite usar métodos con associatedtype, se requiere un complicado type erasure, el código no compila o funciona de manera subóptima.
Ventajas:
Desventajas:
ViewBuilder en SwiftUI utiliza some View, ocultando detalles, aumentando la seguridad de tipos, mejorando la velocidad de compilación y runtime.
Ventajas:
Desventajas: