Class es un tipo por referencia (reference type) en el lenguaje Swift, cuyas instancias se pasan por referencia y no se copian al asignarse. A diferencia de las estructuras, las clases admiten herencia, desinicialización y conteo automático de referencias ARC para la gestión de memoria. Según la Swift Programming Language Guide, 2026, class es necesaria para trabajar con los frameworks de UI de Apple (UIKit, AppKit) e implementar patrones que requieren identidad compartida del objeto. La elección entre class y struct es una de las decisiones arquitectónicas clave en Swift.
Puntos clave
Class — un tipo compuesto por referencia en Swift que agrupa propiedades y métodos en una entidad única con soporte de herencia y envío dinámico. A diferencia de struct, una instancia de clase se crea en el heap, y una variable almacena una referencia a esta instancia, no los datos en sí.
Cuando asigna una variable de clase a otra variable, ambas referencian el mismo objeto en memoria. Los cambios a través de una referencia son visibles a través de la otra — esta es una propiedad fundamental de los tipos por referencia, utilizada en patrones de delegación, observación y estado compartido.
Según la Documentación de Apple Swift, las clases son la única forma de trabajar con UIKit y AppKit, donde todos los componentes de UI heredan de UIView y UIViewController. Además, las clases son necesarias para implementar patrones que requieren identidad de objeto (dos referencias a un objeto) y ciclo de vida controlado.
La semántica de tipo por referencia — la propiedad clave de las clases. Al asignar una clase a una nueva variable, Swift copia la referencia, no los datos. Todas las variables que referencian la misma instancia ven su estado actual y pueden modificarlo. Este comportamiento difiere fundamentalmente de los tipos por valor, donde cada variable obtiene una copia independiente.
// Ejemplo de semántica de tipo por referencia
class User {
var name: String
init(name: String) { self.name = name }
}
let user1 = User(name: "Alice")
let user2 = user1 // user2 — misma referencia
user2.name = "Bob"
print(user1.name) // "Bob" — cambiado a través de user2!
// Verificación de identidad con el operador ===
print(user1 === user2) // true — mismo objeto
Los operadores === (identidad) y !== verifican si dos variables referencian la misma instancia de clase. Esto difiere de == (igualdad), que compara valores de propiedades. El operador === no está disponible para struct — los tipos por valor no tienen identidad.
Herencia — un mecanismo mediante el cual una clase puede adoptar las propiedades y métodos de una clase padre. En Swift, una clase solo puede heredar de un padre (herencia única), pero puede implementar múltiples protocolos. La palabra clave override permite sobrescribir un método o propiedad heredados.
Cualquier clase que no herede de otra clase automáticamente se convierte en base (no confundir con NSObject). Una subclase especifica el padre con dos puntos después de su nombre. Si una subclase sobrescribe un método del padre, debe llamar a super.método() para preservar el comportamiento del padre — este es un requisito del compilador.
La palabra clave final antes de class impide la herencia. El compilador puede optimizar las llamadas a métodos de una clase final mediante envío estático, mejorando el rendimiento. Use final para clases no destinadas a extensión — documenta su intención y acelera el código.
// Ejemplo de herencia de clases en Swift
class Vehicle {
var speed: Double = 0
func description() -> String {
"Speed: \(speed) km/h"
}
}
// Car hereda de Vehicle
class Car: Vehicle {
var brand: String = "Unknown"
override func description() -> String {
"\(brand) - \(speed) km/h"
}
}
// Clase final — impide la herencia
final class ElectricCar: Car {
var batteryLevel: Double = 100
}
let tesla = ElectricCar()
tesla.brand = "Tesla"
tesla.speed = 120
print(tesla.description()) // "Tesla - 120.0 km/h"
La herencia es un mecanismo potente pero responsable. Las jerarquías profundas (más de 5 niveles) complican el mantenimiento y las pruebas. Para la reutilización funcional sin herencia, use protocolos con extensiones y programación orientada a protocolos — un enfoque que Apple promueve como alternativa a las jerarquías profundas de clases.
Swift utiliza ARC (Conteo Automático de Referencias) para la gestión de memoria de las clases. Cada instancia de clase tiene un contador de referencias fuertes. Cuando se crea una nueva referencia fuerte, el contador aumenta; cuando se destruye, disminuye. Cuando el contador llega a cero, la memoria se libera.
Deinit — método que se llama automáticamente antes de liberar una instancia de clase. Libera recursos: cierra archivos, cancela suscripciones a notificaciones, detiene temporizadores. Deinit solo está disponible en clases — las estructuras y enumeraciones no lo tienen.
Para prevenir ciclos de referencias fuertes (retain cycles), Swift proporciona referencias weak y unowned. Weak es una referencia opcional que automáticamente se vuelve nil cuando el objeto se libera. Unowned no es opcional, pero referencia un objeto que se garantiza que vive más que el contexto actual. Un ciclo típico de retain ocurre en una relación padre-hijo: el hijo mantiene una referencia fuerte al padre.
// Ejemplo de ARC y referencia débil
class Parent {
var name: String
var child: Child?
init(name: String) { self.name = name }
deinit { print("\(name) desasignado") }
}
class Child {
var name: String
weak var parent: Parent? // weak previene el ciclo de retención
init(name: String) { self.name = name }
deinit { print("\(name) desasignado") }
}
var parent: Parent? = Parent(name: "Anna")
parent?.child = Child(name: "Mia")
parent?.child?.parent = parent
parent = nil // ¡Ambos objetos desasignados!
// Sin weak crearía un ciclo de retención
Use siempre weak para referencias de un objeto hijo a su padre y para listas de captura en closures. Use unowned solo cuando esté seguro de que el objeto sobrevivirá al contexto actual — el uso incorrecto de unowned puede causar un crash al acceder a memoria liberada.
La elección entre class y struct es una decisión arquitectónica que afecta el rendimiento, la seguridad en hilos y el diseño de API. Considere la tabla de diferencias clave para tomar la decisión correcta en cada caso.
| Característica | class | struct |
|---|---|---|
| Tipo | Tipo por referencia | Tipo por valor (copia) |
| Memoria | Heap + ARC | Stack / inlined |
| Herencia | Soporta (padre único) | No soporta |
| Deinit | Disponible | No disponible |
| Identidad (===) | Soporta | No soporta |
| Mutating | No requerido (siempre mutating) | Solo con mutating |
| Init memberwise | No se genera | Se genera automáticamente |
| Seguridad en hilos | No garantizada (estado compartido) | Garantizada (copia) |
Use clases cuando necesite identidad compartida (múltiples partes del código trabajando con un objeto), herencia o interacción con Objective-C runtime. Para todo lo demás, las estructuras son preferibles — son más rápidas, más seguras en código multihilo y no requieren gestión de memoria.
A pesar de la recomendación de Apple de usar struct por defecto, las clases son necesarias en varios escenarios específicos. Examinemos cada uno con ejemplos prácticos.
Todos los componentes de UI en iOS y macOS son clases que heredan de UIView (iOS) o NSView (macOS). No puede reemplazar UIViewController con una struct — requiere herencia y deinit para liberar recursos. Al trabajar con UIKit, use clases para controladores, vistas y sus delegados.
El patrón Singleton (una instancia de clase para toda la aplicación) requiere semántica de referencia. Los gestores: NetworkManager, SettingsManager, AnalyticsService — normalmente se implementan como clases con una propiedad static compartida. Las estructuras no son adecuadas porque cada copia sería una instancia independiente.
Cuando un objeto debe ser la única fuente de verdad y se pasa entre módulos por referencia — use class. Esto se aplica a la gestión de estado, donde cambiar un objeto en un lugar debe ser visible en todos los componentes dependientes. Para ObservableObject en SwiftUI, las clases son obligatorias.
// ObservableObject — class requerida para SwiftUI
import SwiftUI
class AppViewModel: ObservableObject {
@Published var isLoggedIn: Bool = false
@Published var username: String = ""
func login(user: String) {
isLoggedIn = true
username = user
}
}
// Uso en una vista de SwiftUI
struct ContentView: View {
@StateObject var viewModel = AppViewModel()
var body: some View {
Text(viewModel.isLoggedIn ? "Bienvenido" : "Iniciar sesión")
}
}
Regla: si un objeto debe tener identidad (dos referencias -> un objeto), ser una instancia única o trabajar con UIKit/Objective-C — elija class. Si un objeto simplemente contiene datos — elija struct.
Preguntas frecuentes
Class es un tipo por referencia en Swift que soporta herencia, desinicialización y ARC para la gestión de memoria. Las instancias de clase se almacenan en el heap y las variables contienen una referencia al objeto, no su copia.
Class — tipo por referencia (se pasa por referencia), soporta herencia y deinit. Struct — tipo por valor (se copia), no soporta herencia, pero implementa protocolos y obtiene init memberwise automáticamente. Swift recomienda struct como tipo predeterminado.
ARC (Conteo Automático de Referencias) — un mecanismo de gestión de memoria para clases de Swift. Cada instancia tiene un contador de referencias fuertes. Cuando el contador llega a cero, la memoria se libera. Las referencias weak y unowned previenen ciclos de retención entre objetos.
Deinit — un método de clase que se llama automáticamente antes de liberar su memoria. Se usa para cerrar archivos, cancelar suscripciones a notificaciones y otras operaciones de limpieza. Deinit solo está disponible en clases — las estructuras no lo tienen.
Use class para componentes de UI de UIKit/AppKit, singleton, ObservableObject en SwiftUI, objetos con identidad compartida (delegate, observer) y al trabajar con Objective-C runtime. Para modelos de datos, DTO y configuraciones, se prefiere struct.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también