Domina los métodos de clase en Swift con un ejemplo práctico: un LevelTracker que desbloquea niveles y un Player que avanza. Aquí verás cuándo usar static o class, cómo separar lógica compartida de la lógica por instancia y por qué mutating e init son clave para un sistema de niveles robusto.
¿Qué es un método de clase en Swift y cuándo usar static o class?
Un método es de clase cuando lo invoca la propia clase y no una instancia. La sintaxis es similar a las properties de tipo: antepones class o static a la declaración del método. Usa class si quieres permitir override en subclases; usa static si no quieres que se sobreescriba. En una estructura, no puedes usar class: solo static.
Un método de clase se llama con el nombre del tipo, no con una instancia.
class permite herencia en clases. static bloquea la sobreescritura.
En struct, solo se permite static.
¿Cómo se invoca un método de clase?
Ejemplo simple con print para mostrar la llamada desde el tipo.
classSomeClass{classfuncsomeMethod(){print("Hola")}staticfuncanotherMethod(){print("Hola")}}SomeClass.someMethod()// Invocado por la clase, no por una instancia.
¿Cómo funciona el LevelTracker con métodos estáticos?
Se define una estructura LevelTracker con estado compartido y de instancia. El estado global se maneja con propiedades estáticas y la lógica común con métodos estáticos. Para cambiar el nivel actual del jugador se usa un método mutating porque modifica la instancia.
highestUnlockedLevel: nivel máximo desbloqueado, compartido por todos los jugadores.
currentLevel: nivel actual de una instancia concreta.
unlock(level:): método estático para desbloquear niveles globalmente.
isUnlocked(level:): método estático que valida si un nivel está disponible.
advance(to:): método de instancia y mutating para actualizar el nivel del jugador.
No mezcles llamadas estáticas e instancia sin el tipo: usa el nombre del tipo para acceder a lo estático.
En struct no se usa class: solo static para métodos y propiedades de tipo.
Marca como mutating los métodos que cambian stored properties de la instancia.
¿Cómo integrar Player y completar niveles?
Player compone un LevelTracker y un nombre. Como hay una stored property sin valor inicial, necesitas un inicializador. Para completar un nivel, primero se desbloquea el siguiente con el método estático y luego se avanza con el método de instancia.
tracker: instancia de LevelTracker.
playerName: nombre del jugador.
init(name:): obliga a inicializar playerName.
complete(level:): desbloquea y avanza al siguiente nivel.
classPlayer{var tracker =LevelTracker()var playerName:Stringinit(name:String){self.playerName = name
}funccomplete(level:Int){// Desbloquear el siguiente nivel de forma global.LevelTracker.unlock(level: level +1)// Avanzar el nivel del jugador._= tracker.advance(to: level +1)}}var player =Player(name:"Juan Gabriel")print(player.tracker.currentLevel)// 1player.complete(level:1)print(player.tracker.currentLevel)// 2if player.tracker.advance(to:7){print("Podemos avanzar hasta el nivel siete")}else{print("El nivel siete sigue bloqueado por ahora")}LevelTracker.unlock(level:7)if player.tracker.advance(to:7){print("Podemos avanzar hasta el nivel siete")}
¿Por qué hace falta un inicializador?
Si una stored property no tiene valor por defecto, debes asignarla en init.
Un fix común es dar un valor vacío, pero es preferible un init(name:) claro.
¿Te gustaría extender este patrón con habilidades, experiencia o logros? Comparte tus ideas y casos de uso en los comentarios.