Diferencias entre Classes y Structs en Swift

¿Para qué sirven Classes y Structs?

En general, classes y structs son los building blocks de un programa, nos permite tener diferentes funcionalidades, propiedades, métodos, etc. Es decir, es la estructura básica de la memoria que permite almacenar datos y calcular funciones.

 

Similitudes entre Classes y Structs

En las dos podemos definir propiedades para guardar valores y definir métodos que proveen funcionalidades. Proveen acceso a su estructura interna mediante subscript. Ambos tienen initializers. Además podemos extender la funcionalidad en diferentes formas. Ambos puedes conformar con protocolos.

 

Diferencias entre Classes y Structs

Existen también diferencias entre ambos, por ejemplo, la herencia (que te permite de una clase heredar códigos de una clase padre). En las classes tenemos los deinitializers que te permiten ejecutar acciones antes de la clase de objeto de destruya. Ademas, y el punto mas importante: el reference counting que cuando estamos manejando clases tenemos que tener en cuenta y sin embargo si estamos manejando structs, como tienen un single owner pues no necesita tanta atención.

 

Creación de Classes y Structs

En clases y structs para crear una instancia, se hacen de forma similar, es básicamente lo mismo, digamos que hay diferentes implicaciones. Lo mismo para acceder a propiedades, etc. Es decir, el uso es exactamente el mismo.

Las Classes tiene funcionalidades extras, pero los struct tienen el default initializers: Cuando creas un Struct, te crea un default initializer por defecto con el nombre de las variables por lo que no es necesario escribir ese código, eso es uno de las características más básicas porque es algo que no parece muy complejo pero que más agradecemos a la hora de desarrollar: Tu creas un struct, defines 3, 4, 5 o 10 propiedades y por defecto ya existe un init, eso es súper cómodo y ya no tienes que volverlo a escribir, está ahí definido y queda listo para usar desde el principio.

Value type vs Reference Type

Structs: value type

Los structs son value types. Ejemplos de values types son: Definimos un coche “Coche 1” y creamos una instancia que va a ser un struct. Si queremos crear un coche nuevo “Coche 2”, definimos una nueva variable que va a ser igual al “Coche 1”. Cuando tenemos esa nueva variable y hacemos un cambio en el “Coche 2”. ¿Qué esperaríamos que pasara con el “Coche 1″ tras el cambio al coche 2? ¿Tendría el cambio? La respuesta es que NO lo tiene.

 

Lo anterior nos lleva a que los structs son value types, hacen que cuando se asigna a una variable o una constante, se copia todos los  valores de la anterior, generando una copia aparte. Otra cosa a enfatizar es que cada vez que pases un struct no solamente cuando se asigna, sino también cuando se pasa en un método, también se copia. Esto te ayuda a no cometer muchos errores que se cometen en programación.

Veamos un ejemplo con coches y colores.

(Aclaración: el coche2 si necesita ser var)

Classes: reference type

Las Classes son reference types, y a diferencia de los structs no estamos copiando valores cuando asignamos una clase, sino que estamos pasando la referencia a memoria de esos valores. Esto significa que si en vez de tener un struct, tengo una clase que representa un coche en el momento en que hago “var coche2 = coche1” y al “coche2” le cambio una propiedad, lo que estoy haciendo es cambiar la propiedad al “coche1” también, porque es una referencia única. Esto en cuanto a mutabilidad tiene implicaciones muy importantes. También tiene implicaciones muy importantes en cuanto al reference counting porque aquí ya entra en juego que varios objetos que pueden estar apuntando a la misma clase y son owners de esa clase y el compilador debe saber cuándo puede de-inicializar ese objeto y cuando no. Se puede crear sin querer retain cycles. Lo más importante a tener en cuenta es cuando asignamos una clase a otro objeto, estamos pasando una referencia a los mismo valores, es decir cuando se cambia uno, se cambia el anterior.

¿Cuándo elegir Structs y cuándo elegir Classes?

En la guía de Swift uno de los criterios a la hora de elegir classes es que si debes modelar algo que tiene un ciclo de vida, lo apropiado es una clase. ¿Qué significa tener un ciclo de vida? Un ejemplo sería un file handler o un socket: Una entidad que abres, realizas unas operaciones y que hay que cerrar. Otros objetos que tienen ciclo de vida son el view controller, que tiene un willAppear, viewDidLoad, deInit…  o un Notification Center. Son objetos vivos que se inicializan y de-init y en este caso siempre se recomienda clases.

Por otro lado, casos como datos que obtienes de la red y que simplemente están representando una estructura simple, por ejemplo si tratando de modelar la información de un  partido de futbol, simplemente los datos como la hora, el nombre del equipo, el nombre del equipo visitante… es decir datos simples que no tienen ciclo de vida, son simplemente como una foto de ciertos datos. En este caso, se recomiendan structs.

Un ejemplo donde entra en contexto tu aplicación y el modelo de objeto que tengas, es por ejemplo si estas modelando en una aplicación personas en la que haya relación de padre e hijos. Tienes una clase padre, y el padre tiene un array de hijos. En este caso, los hijos siempre van a tener ese padre en común, y los hijos pueden no serlo pero, pero no quieres tener la misma copia del padre para cada hijo, quieres tener una clase padre y que los hijos tengan una referencia al mismo padre. De esta forma, si al padre le cambias una propiedad (que cumple un año más por ejemplo), se cambia automáticamente a todos los hijos,  ya que tienen la referencia al mismo objeto en común se cambia. Si tuvieras structs, tienes que cambiar al struct padre de todos los hijos porque lo has modificado. Este es un ejemplo fácil en el que ves como con las clases compartes un objeto, compartes los datos, es una referencia y con los structs es una copia.

En cuanto al tema de mutability, es importante ya que la mutabilidad es un aspecto de seguridad y crítico en las aplicaciones el hecho de saber que tus datos no van a cambiar cuando no esperas que cambien y entonces hay que tener muy en cuenta. Con las clases la mutabilidad tiene un alto porcentaje de suceder porque compartes referencias, con los structs en cambio es prácticamente imposible, tú tienes una copia de algo cuando pasas structs por tu aplicación entre funciones, métodos o los copias. Son copias y no hay opción a mutabilidad: Una de las claves de los structs es que cuando se cambia un dato se genera un modelo nuevo, se genera una copia nueva y no se modifica la que ya tienes.

Por defecto los tipos de datos básicos en Swift son structs. En el pasado con Objective-C eran clases.

Deja un comentario