Estructuras vs Clases en Programación Orientada a Objetos

Clase 2 de 27Curso de Programación Orientada a Objetos en Swift

Resumen

Comprende con claridad las diferencias entre estructuras y clases en Swift: qué comparten, qué las distingue y cómo usarlas en programación orientada a objetos. Con ejemplos simples, verás propiedades, instanciación y mutabilidad paso a paso, sin perder de vista conceptos como herencia, casting, desinicializador y reference counting.

¿Qué comparten y qué diferencia a estructuras y clases?

Ambos tipos permiten modelar datos y comportamiento de forma consistente. Comparten rasgos esenciales de la programación orientada a objetos:

  • Propiedades y métodos: definen estado y comportamiento.
  • Subíndices: acceso tipo colección en Swift.
  • Inicializadores o constructores: creación controlada de instancias.
  • Extensiones: añadir funcionalidades a futuro.
  • Conformidad a protocolos: adoptar contratos de comportamiento.

Las clases, además, incorporan capacidades extra que marcan la diferencia:

  • Herencia: una clase adopta funcionalidad de una clase madre.
  • Casting: reinterpretar valores entre tipos compatibles.
  • Desinicializador: liberar recursos al finalizar la vida de la instancia.
  • Reference counting: sistema que registra cuántos fragmentos de código referencian la misma instancia en tiempo de ejecución.

Estas ideas habilitan habilidades clave: identificar cuándo un tipo necesita heredar, cuándo basta con protocolos y extensiones, y cómo pensar en el ciclo de vida de objetos con inicializadores y desinicializadores.

¿Cómo se definen e instancian con sintaxis de Swift?

La sintaxis básica es paralela: cambia solo la palabra reservada. Esto facilita empezar sin distracciones mientras interiorizas los conceptos.

// Estructura básica
def struct SomeStruct { }

// Clase básica
class SomeClass { }

Un ejemplo práctico: modelar la resolución de un vídeo con una estructura, y el modo de reproducción con una clase que la usa como composición.

struct Resolution {
    var width = 0
    var height = 0
}

class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}

Puntos clave que aparecen aquí:

  • Stored properties: width, height, resolution, interlaced, frameRate, name almacenan estado.
  • Opcionales: name: String? puede ser nil o tener valor.
  • Composición: VideoMode contiene una Resolution.

Instanciación y acceso a propiedades:

let someResolution = Resolution()
let someVideoMode = VideoMode()

print(someResolution.width) // 0

someVideoMode.resolution.width = 1280
print(someVideoMode.resolution.width) // 1280

Esta práctica fortalece habilidades de lectura de código, creación de tipos y trabajo con propiedades opcionales y no opcionales.

¿Qué pasa con mutabilidad, constantes y memoria?

Aquí emerge una diferencia esencial en el uso cotidiano:

  • Estructuras (tipos por valor): si creas una instancia como constante con let, su estado no puede cambiar.
  • Clases (tipos por referencia): si creas una referencia como constante con let, puedes modificar sus propiedades variables; lo que no cambia es la referencia de memoria.

Observa el comportamiento al intentar mutar cada caso:

let someResolution = Resolution()
let someVideoMode = VideoMode()

// Estructura como constante: no se puede mutar su estado.
someResolution.width = 1280 // Error: 'someResolution' es una constante.

// Clase como constante: sí se pueden cambiar sus propiedades variables.
someVideoMode.frameRate = 30.0
print(someVideoMode.frameRate) // 30.0

Ideas a interiorizar para escribir código robusto:

  • Inmutabilidad con let: en estructuras, bloquea cambios de estado.
  • Referencia constante: en clases, fija la dirección de memoria, no el estado interno.
  • Diseño intencional: usa estructuras para contenedores de datos simples (p. ej., Resolution). Emplea clases cuando haya reproducción de vídeo, estado cambiante o relaciones que más tarde puedan requerir herencia.
  • Terminología útil: diferencia entre stored properties y computed properties; las segundas calculan valores a demanda. En clases, ambas pueden cambiar si se declaran como variables.

¿Cómo pensar su uso en programación orientada a objetos?

  • Prioriza estructuras para modelos de datos simples e independientes.
  • Recurre a clases si anticipas herencia, casting o gestión de ciclo de vida con desinicializador.
  • Extiende tipos con extensiones y organiza comportamiento con protocolos para componer capacidades sin herencia prematura.

¿Tienes dudas o quieres proponer un ejemplo con tus propios modelos de datos? Comparte tu caso y lo revisamos juntos.

      Estructuras vs Clases en Programación Orientada a Objetos