Estructuras y Protocolos en Swift 3

| 2017-08-22 | No hay comentarios »

Estructuras

Datos por valor o por referencia

Un struct es básicamente, una estructura de datos o al menos ese es su objetivo o representación. Pero vista desde un punto de vista más amplio a nivel de Swift podemos pensar que un struct es un realidad una clase sin herencia y cuyo principal objetivo es crear una estructura de código que pueda ser representada a partir de un tipo de dato por valor y no por referencia.

Mientras los tipos de dato por referencia suponen la base de la orientación a objetos, donde una variable o constante no contiene el dato en sí, si no la dirección de memoria (o referencia) donde esté el objeto almacenado, un struct es un dato por valor donde el dato en sí está almacenado en la variable o constante directamente. Es básicamente la diferencia entre apuntar el cajón donde guardamos las cosas en una lista donde en cada línea enumeramos todos los cajones de un inventario y lo que contienen (por referencia) o a ponerle una etiqueta directamente al cajón para saber qué hay dentro (por valor).

A efectos de programación, asignar una variable con un dato por referencia a otra (un objeto creado a partir de una clase), hace que ambas variables apunten y hablen del mismo objeto. Pero en un struct esto no es así: al igual que un array o cualquier tipo de colección de Swift, dato numérico o cadena, cuando se asigna una variable con un struct a otra, en realidad estamos haciendo una copia idéntica que, a partir del momento de la copia, se convierten en dos estructuras de datos completamente independientes y sin relación alguna, salvo en su definición base.

Struct, inicializadores por defecto

Cuando creamos un struct no necesitamos crear un inicializador si no simplemente decir qué datos queremos almacenar en el mismo como propiedades o qué métodos queremos que le acompañen. Nada más. Imaginemos una estructura para un auto.

struct Auto {

    var ruedas: Int

    var puertas: Int

    var color: String

}

Cuando creamos una nueva variable y decimos que sea un tipo struct Auto, al escribir el primer paréntesis el sistema ya nos permite elegir en su ayuda en línea la creación del constructor por defecto donde vamos a darle valor a todas y cada una de las propiedades no opcionales del mismo.

let auto1 = Auto(ruedas: 4, puertas: 4, color: "Rojo")

auto1.ruedas

podemos copiar auto en una nueva variable auto2,  y podremos modificar los valores de las propiedades sin problema alguno.

var auto2 = auto1

auto2.ruedas = 2

auto2.ruedas

Y esto, en esencia, son los structsUna estructura de datos similar a una clase, pero que como hemos dicho sin herencia y en datos por valor. Los structs, igualmente, permiten usar protocolos de forma que podemos construir especificaciones que queramos que encajen con este (se conformen) y ahí es donde está la clave para la nueva orientación a protocolos que incorpora Swift 2. A partir de implementaciones por defecto y de la herencia que sí permiten los protocolos, nos permite construir un nuevo tipo de abstracción basado en datos por valor que, al final, resultan más eficientes a nivel de memoria para algunos casos en que trabajemos con Swift.

Protocolos

¿Qué es un protocolo? Es una plantilla a usar cuando queremos tener una especificación común a una serie de clases, structs o enumeraciones. Un protocolo nos permite indicar las cabeceras de funciones o propiedades que queramos se incluyan de manera obligada para cumplir con una especificación que, posteriormente, tendrá una implementación asociada (un código que le de funcionalidad).

Usamos la palabra clave protocol y luego podemos incluir funciones, indicando solo la cabecera que corresponde, o propiedades donde no podemos usar almacenadas si no solo propiedades calculadas que incluyan métodos get o set. En el caso expuesto solo usamos get, pero si tuviéramos la ocasión de usar también el set, simplemente ponemos { get set }. Ejemplo:

protocol Mortal {

    var muerto: Bool { get }

    func muerte()

}

class Pj {

    var nombre: String

    var vida: Int

    init(nombre:String, vida:Int) {

        self.nombre = nombre

        self.vida = vida

    }

}

class Villano: Pj, Mortal {

    var muerto:Bool {

        return vida <= 0

    }

 

    func muerte() {

          print(“Muerteeeeeee”)

    }

}

Cuando creamos la nueva clase, y especificamos que estamos creando una subclase de Pj, seguido con coma ponemos el protocolo y eso nos obliga a incluir aquello que hemos hecho que forme parte del protocolo. Con esto, conseguimos lo que se denomina conformarse a un protocolo. Si quitáramos cualquiera de los dos componentes del protocolo, veríamos que obtenemos un error inmediato porque los protocolos en Swift son obligatorios.

Acerca del autor: Rodrigo Paszniuk

Ingeniero Informático, amante de la tecnología, la música, el ciclismo y aprender cosas nuevas.

Posts Relacionados

  • Manual básico de Swift 3
  • Tuplas y Enumeraciones en Swift 3
  • Clases en Swift 3
  • Funciones en Swift 3



SEGUÍNOS EN FACEBOOK


GITHUB