Clases y herencia
Una clase es una plantilla para la creación de objetos de datos según un modelo predefinido. Las clases son un pilar fundamental de la programación orientada a objetos. Permiten abstraer los datos y sus operaciones asociadas al modo de una caja negra. Los lenguajes de programación que soportan clases difieren sutilmente en su soporte para diversas características relacionadas con clases. La mayoría soportan diversas formas de herencia. Muchos lenguajes también soportan características para proporcionar encapsulación, como especificadores de acceso.
class ClaseEjemplo { var atributo: Int = 0 } class ClaseEjemplo2 : ClaseEjemplo{ }
Hemos definido una clase llamada ClaseEjemplo y otra clase llamada ClaseEjemplo2 que hereda de ClaseEjemplo.
Clases y structs
Una clase y un struct son muy similares, de hecho, en Swift son casi iguales. Su única diferencia es que mientras una actúa en paso por referencia (la clase) la otra se copia a sí misma en cada nueva asignación (el struct). Los structs, por otro lado, permiten declarar una estructura de datos que no requiere inicializar ninguna de sus variables.
Vamos a crear un struct que represente los valores de fuerza y vida como valores vitales y lo sustituimos en nuestra clase Persona.
struct valoresVitales { var fuerza: Int var vida: Int }
class Persona { let nombre: String let vital: valoresVitales init(nombre: String, vital: valoresVitales) { self.nombre = nombre self.vital = vital } }
Debido a cómo Swift maneja las variables y las constantes en objetos, cuando definimos una instancia de una clase como constante (en let) podremos cambiar las propiedades de esta sin problema, aunque no podremos re-asignar la constante a una nueva clase.
Sin embargo, un struct constante no permite alterar las propiedades de la misma ni tampoco, como pasa con las clases, re-asignar dicha constante a un nuevo struct.
Como vemos, la inicialización de una clase se basa en la palabra clave init, donde pedimos aquellos parámetros que consideremos necesarios para la inicialización. Si tras crear nuestro inicializador, alguna propiedad de la clase no quedara asignada, nos daría error, pues recordemos que en Swift todo ha de ser inicializado con valor en el momento de su creación, incluso las opcionales que llevan un valor vacío y wrapeado que se asigna en el momento de la creación del mismo opcional.
Inicializadores de conveniencia
Ya hemos creado nuestra clase Persona, y para inicializarla tenemos que pasarle el nombre del mismo como parámetro, pero también tenemos pasarle la iniciación de un struct que corresponda con sus valores vitales.
var vital = valoresVitales(fuerza: 30,vida: 50) let Hombre = Persona (nombre: "Shagrat", vital: vital)
convenience init (name:String, fuerza:Int, vida:Int) { let vital = valoresVitales(fuerza: fuerza, vida: vida) self.init (nombre: name, vital: vital) }
let Hombre = Persona (name: "XXX", fuerza: 30, vida: 50)
Herencia extendida
Ejemplo de como crear una nueva clase que extienda por herencia la funcionalidad de una clase padre:
class Animal { var patas: Int init(patas: Int) { self.patas = patas } } class Perro: Animal { let habilidad: String init(patas: Int, habilidad: String) { self.habilidad = habilidad super.init(patas: patas) } } let perro = Perro(patas: 4, habilidad: "Ladrar") print(perro.patas)
Con eso, estaremos creando una clase Perro que hereda de Animal pero extiende sus propiedades añadiendo un nuevo valor habilidad.