En este Tutorial Swift vamos a aprender sobre el control de acceso, qué áreas de nuestro código serán mutables desde el exterior, qué funcionalidades de nuestros objetos son compartidas en su interfaz pública y cuales no.

Esta es una característica que se encuentra en la mayoría de los lenguajes de programación modernos, por no decir en todos. La razón detrás de su existencia reside en la necesidad de proteger ciertos segmentos del código que no necesitan estar expuestos a que por equivocación sean modificados desde otras áreas de nuestra aplicación.

Por ejemplo, supongamos que tenemos una propiedad que es usada solamente dentro de la definición de clase y deseamos que esta no pueda ser visible desde el exterior. Pues con el Control de Acceso podemos administrar la visibilidad de esta propiedad y ocultarla a otras áreas del programa, es decir encapsulamos el método de accesos externos probablemente de consecuencia indeseada ya que este no está concebido para interacciones ajenas a la propia clase que lo define.

Modulos y Códigos Fuente

El Control de Acceso se organiza en dos importantes conceptos que están relacionados: los módulos y los códigos fuentes. Un módulo es una unidad de código que se desarrolla y se distribuye como un todo, puede ser tanto un framework como una aplicación que luego puede ser importado por cualquier otro módulo haciendo uso de la palabra clave import.

Para entender mejor esto hagamos referencia a algo que imagino todos recordaran haber visto: import UIKit o import Cocoa al inicio de los playgrounds o de cualquier código fuente, pues estos son frameworks que agrupan una serie de tipos y funcionalidades relacionadas. Por ejemplo, UIKit es un framework diseñado para facilitar el desarrollo de las interfaces gráficas de usuario.

Los códigos fuentes por su parte, constituyen una unidad más discreta, que representa un archivo y forman parte de un módulo específico. Con respecto a esto último sería bueno agregar que se considera una buena práctica definir un solo tipo por cada código fuente, esto no es obligatorio pero ayuda a mantener el proyecto organizado.

Niveles de Acceso

En el lenguaje Swift contamos con tres niveles de acceso:

Nivel de Acceso Descripción
Public El acceso público hace que las entidades sean visibles a todos los archivos en el módulo o a aquellos que hayan sido importados por el módulo.
Internal El acceso interno (por defecto) hace que las entidades sean visibles a todos los archivos en el mismo módulo.
Private  El acceso privado hace las entidades visibles solamente dentro del archivo de código fuente donde este se define.

En general, el nivel de acceso que utilicemos debe de ser consistente a su vez con el nivel de acceso de sus propiedades y métodos. Una propiedad no puede tener un nivel de acceso menos restrictivo que su propio tipo. Por ejemplo una propiedad con un nivel de control de internal no puede ser declarada en un tipo con acceso private. Igualmente, el control de acceso de una función no puede ser menos restrictiva que el control de acceso listado para sus parámetros. Evidentemente si violamos estos requerimientos, el compilador nos mostrará un error.

Como ya hemos comentado el nivel de acceso por defecto que establece Swift para nuestras aplicaciones es internal. Este hecho permite que no sea necesario especificar de manera explícita el nivel de acceso de cada tipo, propiedad y método en el código. Dicho esto solamente tendríamos que especificar el control de acceso cuando sea necesario especificar public y private.

Veamos un ejemplo práctico:

…la salida en pantalla sería:

Aquí tenemos un código bastante trivial, sencillo. En la línea 7 establecemos la propiedad opcional someValue como privada en pos de que solamente se pueda interactuar con ella desde el interior de la clase o desde el mismo archivo donde esta se define.

Como parte de esta clase también contamos con un método llamado isEmpty, su función consiste en verificar si la propiedad someValue cuenta con un valor asignado o aún está vacía. Esto último pudiera también ser dicho como que nos encontramos verificando si aún esta propiedad es igual a nil. A través de este método los clientes de la clase delegan la verificación en nosotros y al mismo tiempo creamos una interfaz entre ellos y la propiedad privada, evitando así que esta puede ser tratada de manera que no consideramos segura.

Pero hay un problema en este código, no podemos leer ni modificar el valor almacenado en la propiedad someValue, aún no hemos creado una interfaz para esto, algo que pudiéramos implementar de distintas maneras en dependencia de la necesidad. Acceder directamente no es posible así que tendríamos que crear un método que nos permita lograrlo.

¿Qué otra opción tendríamos?

Pues a mi modo de ver la opción más óptima y al mismo tiempo más al estilo de Swift sería implementar el nivel de acceso directamente sobre la funcionalidad get y set de la propiedad, para luego definir un método que nos permita mutar su valor. Veamos:

En esta línea hemos modificado los controles de acceso, ahora tenemos internal como primer nivel de acceso haciendo referencia a la funcionalidad get, es decir que cualquiera dentro de todos los archivos de nuestro módulo podrá consultar el valor almacenado en la propiedad.

¿Cómo sabemos que en esta línea internal hace referencia a get y no a set?

Esto se aclara por si mismo ya que seguido de este tenemos otro nivel de acceso private(set) donde claramente se hace referencia a set de manera explícita, es decir, que en una sola línea hemos declarado los niveles de acceso necesarios, más sencillo imposible.

Ahorita necesitamos un método con nivel de acceso internal que nos permita filtrar el nuevo valor ya que no podemos confiar en que el usuario siempre lo pasará en mayúsculas que es como lo necesitamos, así que le daremos formato antes de almacenarlo. El método del que hablamos pudiera ser el siguiente:

Como ven este método no tiene nada de especial, de hecho ni siquiera hemos declarado la palabra clave internal, pero no es necesario ya que por defecto la clase, sus propiedades y métodos se encuentran en un nivel de acceso internal.

El código final sería:

…la salida en pantalla:

Como hemos visto el lenguaje de programación Swift, como otros lenguajes, nos brinda la opción de restringir el acceso a clases, funciones, variables, estructuras, enums, etc, aplicando así los niveles de control de accesos requeridos por nuestro diseño, de esta manera restringimos o permitimos la interacción entre los distintos bloques de código que conformen nuestro proyecto.

Para más información y ejemplos podemos dirigirnos a la documentación oficial de Swift (Inglés) en el sitio de desarrolladores de Apple.

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!