Historia de la cuestión:
El shadowing (sombreado) es un fenómeno en el que se declara una variable con el mismo nombre en el ámbito interno, ocultando (sombreando) la variable del ámbito externo. En las versiones tempranas de Swift, el compilador no era estricto en cuanto al shadowing, pero con la complejidad del modelo del lenguaje, la identificación explícita de tales casos se volvió obligatoria para evitar errores.
Problema:
El shadowing dificulta el mantenimiento del código y genera errores difíciles de detectar: la declaración accidental de una variable con el mismo nombre puede llevar a que el acceso no se realice a la variable que el desarrollador espera. Esto es especialmente crítico en casos de transmisión de variables por referencia y dentro de bucles o cierres, ya que los errores a menudo se manifiestan solo en tiempo de ejecución.
Solución:
Swift permite el shadowing de variables, pero se recomienda evitar el sombreado de variables o propiedades importantes, utilizar diferentes nombres o emplear referencias explícitas de self/this. Especialmente en los inicializadores de struct/class se recomienda utilizar self para distinguir entre el miembro y el parámetro:
Ejemplo de código:
struct User { let name: String init(name: String) { self.name = name // self asegura la claridad de la asignación } }
Características clave:
¿Qué sucede con el shadowing en bucles y cierres?
Si se declara una variable dentro de un cierre con el mismo nombre que en el contexto externo, el shadowing ocultará la variable externa. A veces, esto provoca un comportamiento inesperado, especialmente en programación concurrente.
let value = 10 let closure = { let value = 20; print(value) } closure() // 20 print(value) // 10
¿Se puede declarar una constante y una variable con el mismo nombre en el mismo ámbito?
No. Swift no permite tener var y let para el mismo nombre dentro del mismo ámbito:
let x = 5 var x = 10 // Error: Invalid redeclaration of 'x'
¿Cómo evitar la confusión con el shadowing de propiedades de clase al heredar?
Si una subclase declara una propiedad con el mismo nombre que la del padre, se produce un shadowing. Sin embargo, al acceder a través de super o self se elegirá la propiedad correspondiente. Es mejor no usar nombres idénticos innecesariamente.
En la clase Account, uno de los desarrolladores accidentalmente usó la variable balance como nombre de parámetro de la función y dentro de la función volvió a usar let balance = .... Debido al shadowing, se realizó el cálculo con el valor incorrecto y la función devolvió un resultado erróneo, el cual solo se descubrió en una etapa avanzada de pruebas.
Ventajas:
Desventajas:
Todo el equipo acordó utilizar prefijos (por ejemplo, inputBalance) o siempre aplicar self para referirse a propiedades. Como resultado, los errores por shadowing prácticamente desaparecieron y el mantenimiento del código se simplificó.
Ventajas:
Desventajas: