Un tipo existencial almacena el valor en una «caja» en el heap (si el valor no cabe en los 3 punteros del existential container) y usa una tabla de funciones virtuales para el dispatch. Esto supone:
- Posible allocación en el heap frente a la pila.
- Dispatch indirecto (virtual) en lugar de directo (estático).
- Imposibilidad de inlining por parte del compilador.
Cuándo usar any y cuándo un genérico
// Genérico: mas eficiente, el tipo se conoce en compilación
func imprimirArea(_ f: F) { print(f.area) }
// Existencial: necesario cuando el tipo no se conoce en compilación
func mostrarFormas(_ formas: [any Forma]) {
for f in formas { print(f.area) }
}
Abrir un existencial (Swift 5.7)
func procesarForma(_ f: any Forma) {
// Swift 5.7: abre el existencial para operar sobre el tipo concreto
// El compilador llama a la version generica interna
let copia = f // el compilador «abre» el tipo aqui
print(copia.area)
}
