En esta ocasión dedicaremos el Tutorial Swift a las Extensiones y como siempre compartiremos una breve explicación sobre esta característica del lenguaje, para luego enfocarnos en ejemplos prácticos.

¿Qué son las extensiones?

La respuesta corta sería que las extensiones en Swift son una muy interesante característica que viene a ampliar un más la versatilidad que este lenguaje de programación nos ofrece, pero hay mucho más que decir sobre este tema.

Para ponernos en contexto y entender mejor su utilidad hagamos un ejercicio mental: imaginemos que estamos desarrollando una aplicación que hace uso frecuente de un tipo de dato – digamos que Double – en particular. Teniendo en cuenta esto sería genial si pudiéramos incorporar algunos métodos adicionales dentro del tipo Double basados en las tareas que estamos efectuando con este. Desafortunadamente, no contamos con la implementación de Double para poder modificarla por lo que no podemos añadir estos nuevos comportamientos directamente.

¿Qué podemos hacer?

Pues para estos casos el lenguaje Swift nos ofrece una característica llamada extensiones o extensions en Inglés. Las Extensiones nos permiten añadir funcionalidades a un tipo existente el cual puede ser un tipo creado por nosotros o los del sistema, es decir que podemos extender estructuras, enumeraciones y clases. Ahora, con el uso de las Extensiones podemos añadir a estos tipos lo siguiente:

  • Propiedades computadas
  • Nuevos inicializadores
  • Adopción de protocolos
  • Nuevos métodos
  • Tipos embebidos

A continuación veremos un ejemplo donde extenderemos un tipo de dato al cual no tenemos acceso, algo similar al ejemplo que acabamos de describir arriba.

Extendiendo un Tipo de Dato Existente

Modelaremos el comportamiento de un carro y estarán de acuerdo conmigo que en estos la velocidad es una característica bien importante y que se encuentra constantemente cambiando. Ahora, debido a que la velocidad puede tener valores decimales creo que representarla con un Double no estaría mal o del todo descabellado, cierto? También deberíamos hacer uso de la palabra clave typealias , que ya hemos visto en otros artículos, para trabajar con Double bajo un nombre – Velocity – que nos resulte más representativo y contribuir así a la buena legibilidad de nuestro código. Por último extenderemos Velocity para añadirle dos propiedades computadas que nos devolverán los kilómetros por hora y las millas por hora. Veamos:

Recordemos que estamos definiendo el comportamiento de un vehículo y en Swift los protocolos son esa característica por excelencia a la hora de definir la interfaz de un tipo. Así que el paso siguiente sería añadir a nuestro código un protocolo que nos ayude con la implementación de las funciones comunes a todos los vehículos:

Aquí tenemos un protocolo bastante sencillo, de nombre VehicleType, donde declaramos tres propiedades a las cuales establecemos la implementación de la funcionalidad get como requerida.

Extendiendo un Tipo Propio

En este punto necesitamos crear un nuevo tipo antes de poder hacer que este adopte un protocolo a través de una extensión. Dicho esto pues declaremos una nueva estructura en representación de un carro:

…como podemos comprobar es nuevamente un código bastante básico, pero lo suficiente para el objetivo de este tutorial. Hemos declarado unas pocas constantes que almacenarán información sobre el vehículo en cuestión al igual que una propiedad almacenada la cual captura, mediante el observador willSet, los cambios efectuados sobre esta y verifica mediante la función precondition si el nuevo valor está entre 0 y 1.

Adoptando un Protocolo a través de Extensiones

Las extensiones nos pueden servir como un gran mecanismo de agrupar bloques de código relacionados, al mismo tiempo que tener estas funcionalidades coincidiendo en una misma extensión nos ayuda bastante con la legibilidad del código, mantenemos la interfaz del tipo Car intacta y por ende también mejora el mantenimiento del código.

El siguiente paso sería extender nuestro tipo Car para que adopte el protocolo VehicleType:

Como podemos constatar la sintaxis para la adopción de un protocolo es la misma que habíamos visto hasta ahora y dentro de las llaves encontramos las propiedades que establece el protocolo como obligatorias.

Añadiendo un Inicializador a través de una Extensión

Recordemos que Swift nos ofrece un inicializador por defecto para las estructuras, pero en ocasiones nos resulta necesario tener una implementación un poco más personalizada de un inicializador. Pues esto también lo podemos lograr con una extensión:

Mediante esta extensión añadimos a nuestro tipo Car un inicializador que solamente toma algunos parámetros para crear una instancia nueva, como por ejemplo:

…la salida en pantalla sería:

Tipos Anidados

Las extensiones en Swift también nos permiten anidar tipos a otros ya existentes. Digamos por ejemplo que ahora queremos añadir a nuestro carro una enumeración que nos ayude a clasificar el tipo de auto que cierta instancia pudiera representar:

En esta nueva porción de código acabamos de extender la estructura Car añadiéndole una enumeración y una propiedad computada. La enumeración de nombre CarKind se apoya, al igual que la estructura Car, en el protocolo CustomStringConvertible en pos de mostrar una descripción textual sobre el tipo en cuestión. En CarKind también hemos definido dos tipos de carros: los CoupeSedanHatchback, y en el caso de la propiedad kind retornamos un tipo de carro u otro en dependencia de la cantidad de puertas.

Extensiones y Funciones

Por último agreguemos dos funcionalidades más:

En este ejemplo hemos definido dos funciones, una que nos permite llenar el tanque de combustible así como otra que lo va consumiendo, y para esto hemos utilizado nuevamente las extensiones. Quizás lo único que habría que comentar o recordar más bien es que Car es una estructura y ambas funciones modifican propiedades miembro, y esta es la única razón por la que tenemos que hacer uso de la palabra clave mutating, es decir que si Car fuera una clase la pudiéramos haber obviado por completo.

El código final sería el siguiente:

…al final hemos añadido un ejemplo de uso, la salida en pantalla es la siguiente:

Creo que está de más decir, aunque es válida la aclaración, que este ejemplo se ha creado con fines didácticos y como apoyo al tutorial, por lo que en un caso real quizás no haya que usar tantas extensiones, Car pudiera haber sido una clase en lugar de una estructura, evidentemente también hubiera tenido muchos más métodos, en fin amigos que todo depende de lo que estemos desarrollando y en el escenario en el que nos encontremos. Espero haber dejado claro lo que son las extensiones, como usarlas y los beneficios de las mismas. Luego de haber aprendido todo cuanto hemos explicado la ocasión de uso vendrá sola a nuestra mente cuando estemos diseñando nuestro código y las interacciones del mismo.

Espero que todo cuanto se ha dicho aquí, de una forma u otra le haya servido de aprendizaje, de referencia, que haya valido su preciado tiempo.

Este artículo, al igual que el resto, será revisado con cierta frecuencia en pos de mantener un contenido de calidad y actualizado.

Cualquier sugerencia, ya sea errores a corregir, información o ejemplos a añadir será, más que bienvenida, necesaria!