Protocolos en Swift como contratos de código

Resumen

Los protocolos en Swift funcionan como contratos: definen qué funciones debe implementar una clase sin dictar cómo resolverlas. Si trabajas con Swift y quieres que tu código sea más flexible, escalable y predecible, dominar este concepto es clave para diseñar arquitecturas limpias.

La idea es simple: cuando una clase adopta un protocolo, queda obligada a cumplir las funciones que ese protocolo declara. Igual que firmar un contrato en la vida real, romperlo no es opción y el compilador te lo recordará.

Qué es un protocolo en Swift y para qué sirve

Un protocolo es una declaración de funciones o propiedades que las clases adoptantes deben implementar. No contiene lógica, solo el enunciado del método. La lógica corre por cuenta de cada clase.

Piensa en una app de transporte con clases como carros, motocicletas, bicicletas, aviones y trenes. Todas comparten algo: se pueden manejar. En lugar de repetir esa idea en cada clase, defines un protocolo EsManejable que obliga a implementar la función correspondiente. Cada clase resuelve la lógica a su manera.

¿Qué es un protocolo en Swift? Es un contrato que define qué métodos o propiedades debe implementar una clase. Solo declara los enunciados, no la lógica. Cada clase que lo adopta resuelve la implementación según su contexto [03:20].

Cómo crear un protocolo Describable paso a paso

En el proyecto, las clases Student y Subject tenían funciones casi idénticas: una devolvía la descripción del estudiante y otra la de la materia. Ese patrón es la señal perfecta para extraer un protocolo.

La solución fue crear un archivo Swift llamado Describable dentro de la carpeta sources con esta declaración:

swift public protocol Describable { func describe() -> String }

Luego, ambas clases adoptan el protocolo usando dos puntos, igual que en herencia:

swift public class Student: Describable { func describe() -> String { // lógica propia del estudiante } }

Si olvidas implementar describe, Xcode marca el error: "type Student does not conform to protocol Describable". Ese mensaje es el contrato recordándote que debes cumplir.

Cómo refactorizar funciones existentes para cumplir el protocolo

Las funciones studentDescription y subjectDescription ya hacían el trabajo, así que solo había que renombrarlas a describe. Después, actualizar todas las llamadas en StudentAvanzado y en el playground para que apunten al nuevo nombre [07:45].

Cómo diseñar un protocolo Manageable para escalar tu código

La clase StudentsManager concentra la lógica del sistema, así que conviene blindarla con un protocolo que garantice un set fijo de funciones disponibles. Esto protege el código del yo del futuro o de cualquier desarrollador que llegue después.

El protocolo Manageable define funciones para:

  • Insertar un estudiante en la lista.
  • Asignar una materia con su score a un estudiante específico.
  • Generar un reporte completo del sistema.
  • Filtrar estudiantes aprobados y reprobados.
  • Calcular el promedio individual de cada estudiante.
  • Calcular el promedio total del sistema como Double.
  • Devolver un Set con todas las materias cursadas sin duplicados.

Por qué Subject debe implementar Hashable

Al declarar un Set<Subject>, Swift lanza un error: los sets exigen que sus elementos cumplan el protocolo Hashable. La solución es adoptarlo junto a Describable:

swift public class Subject: Describable, Hashable { // ... }

¿Por qué necesito Hashable para usar Set en Swift? Porque los sets requieren que sus elementos sean hasheables para garantizar unicidad. Sin Hashable, Swift no puede comparar ni almacenar los elementos sin duplicados [13:10].

Cómo implementar las funciones core de StudentsManager

Xcode ofrece un fix automático que genera los stubs de todas las funciones del protocolo. Para evitar errores de compilación mientras se desarrolla, las funciones que retornan algo devuelven valores vacíos temporalmente: listas vacías, un 0 para el promedio total y un set vacío para las materias.

Las tres primeras funciones ya se pueden resolver con lo visto:

  • insertStudent: cambia la lista students de let a var y aplica append con el estudiante recibido por parámetro.
  • asignarMateria a estudiante: agrega una función asignarMateria en la clase Student que reciba materia y score, y haga append en las listas subjects y scores. En StudentsManager, recorre la lista con un for, compara emails usando elementsEqual y, al encontrar coincidencia, llama a la función con los parámetros correspondientes.
  • generar reporte: recorre la lista de estudiantes y ejecuta print(student.describe()) para cada uno [17:30].

Un detalle importante: si tus listas internas están declaradas como let, no podrás modificarlas. Cámbialas a var antes de aplicar append.

Qué función usar para comparar strings en Swift

En lugar del clásico ==, el ejemplo usa elementsEqual, que compara secuencias elemento a elemento. Es equivalente para strings y deja explícita la intención de comparación.

Esta arquitectura con dos protocolos, Describable y Manageable, deja el sistema preparado para crecer sin romper contratos. ¿Cómo te fue resolviendo las tres funciones por tu cuenta? Cuéntame en los comentarios qué dificultades encontraste.