Swift logotipo

Swift – Instancias y clases

Imaginemos que tenemos un banco que tiene cuentas corrientes, créditos y empleados (entre otros). Entonces, a “cuentas” se la conoce como una instancia del banco. Cuentas tiene la capacidad y las funciones de realizar transferencias, despóticos o retiros. Cosa que no tiene, por ejemplo, créditos o empleados. 

Clase, método e instancia

Por tanto, una instancia en programación es una extensión del contenido y puede variar según las diferentes operaciones. 

Un banco en programación sería una clase o estructura, la cual podemos extenderla como instancia, ya que tiene dentro métodos o funciones propias que la definen como tal. Un método es una función que se encuentra dentro de una clase o estructura. 

Clases y objetos

Para continuar desarrollando de forma simple el concepto anterior, es interesante realizar un ejemplo parecido al anterior, asociándolo las clases a las mascotas. 

Las mascotas vienen siendo una clase, conformado por diferentes objetos que pueden ser perros, gatos y peces. Estos objetos tienen métodos, que no pueden hacer otros objetos. Por ejemplo, el método maullar sólo lo puede hacer el objeto gato y el método ladrar sólo lo puede hacer el objeto perro. Pero el perro no maúlla y el gato no ladra. También los objetos, pueden tener propiedades (grande, gordo o blanco). Como sabemos, nosotros podemos instanciar una clase. Por ejemplo, podemos crear una nueva instancia que se llaman Aves. Un nuevo objeto llamado Aves es una extensión o instancia de la clase mascotas. El objeto Aves tiene un método llamado volar, que no puede hacer ni los perros ni los gatos, ni lo peces. Un objeto es un término usado para referirse a una instancia de una clase o estructura. 

Clase o estructura, objetos y métodos
Clase o estructura, objetos y métodos

Finalmente, todos los objetos, instancias y métodos pertenecen a la misma clase llamada mascotas. 

Para finalizar esta sección se pueden hacer estas equivalencias. 

  • Clase o estructura equivale a “el programa”.
  • Instancia equivale a: Objeto o extensión. 
  • Método equivale a: Función dentro la clase. 

Una clase o estructura engloba al programa. Sin embargo, más adelante veremos las principales diferencias entre clases y estructuras.

Como crear una instancia

En Swift para crear una instancia, primero declaramos una constante empleando la palabra clave reservada «let» y luego la inicializ amos con el nombre del tipo seguido por los paréntesis. Por ejemplo hemos dicho al principio que «cuentas», es una instancia del banco. Por lo que la forma de crear una instancia sería:

 let cuentas = Cuentas()

Definición de Clase

Para crear una clase, iniciemos Xcode y creemos un nuevo playground. Entonces, eliminamos todos los contenidos del playground y añadimos la siguiente definición de clase.

class animal {
  //Aquí va el resto del código
}

Se puede resumir que con la palabra “class” estamos bautizando un programa que se llama “animal” y va entre corchetes. Si alguna vez hemos empleado Visual Basic, la clase se denomina módulo y va entre Sub animal() y end Sub. Animal es el nombre del programa.
El programa animal, hará algo. Es decir, caminar, maullar, comer, etc.

Propiedades

Antes hemos hablado que un objeto o una instancia puede ser un determinado tamaño, color o peso. Es decir, en las propiedades estamos definiendo las características de la clase. Para ello, emplearemos variables “var” y constantes “let”. Éste tipo de propiedades se conocen como propiedades almacenadas. Existe otro tipo de propiedades, llamada propiedades computadas.

  • nombre, una propiedad variable de tipo String?
  • raza una propiedad variable del tipo String?
  • sexo: una propiedad constante de tipo String
class Animal {
 var nombre: String?
 var raza: String?
 var edad: int?
 let sexo = "hembra"
}

Definir propiedades es definir variables y constantes dentro de una clase. Una propiedad almacenada, como las anteriormente definidas, ha de tener un valor o ser del tipo opcional.

El Init()

Toda clase que contenga propiedades (variables) necesita un inicializador y se crea con la palabra reservada init().

class Animal {
 var nombre: String
 var raza: String
 var edad: int
 var sexo: String

init (nombre: String, raza: String, edad: int, sexo: String){
  self.nombre = nombre
  self.raza = raza
  self.edad = edad
  self.sexo = sexo
 }
}

Sin embargo, el “init” no es necesario si ponemos las variables en opcional. Es decir, con símbolos de interrogación “?”. La palabra clave reservada init(), no está precedida por la palabra clave reservada “func”.
Una de las cosas que nos permite realizar el init, es forzar el cambio de una constante. Imaginemos lo siguiente:

class Animal {
 var nombre: String
 var raza: String
 var edad: int
 let sexo = “macho”

  init (){
   self.sexo = “hembra”
  }
}

Métodos

Los métodos agregan funcionalidades a una clase. Como hemos indicado un método es una función en el contexto de las clases. Hablar de métodos o funciones es algo muy parecido, cuando no igual. Veamos un ejemplo simple de funciones:

Class incremental {
 var i = 0

func incremento() {
 i = i + 1
 }
}

let contar = Contador()
contar.incremento()
println(contar.i)

Fijémonos que hemos hecho. Primero hemos creado una función que lo que hace es sumar el valor actual con el anterior. Luego, para imprimir el valor nuevo de “i” fuera de la clase, hay que crear una instancia de la siguiente manera: let contar = incremental()

Luego, llamamos a la función que está dentro de la clase: contar.incremento() y finalmente imprimimos el valor.


Instanciar

Hemos definido una clase con unas cuántas propiedades y un método. Para crear una instancia de la clase animal lo hacemos de la siguiente manera:

class Animal {
 var nombre: String?
 var raza: String?
 let sexo = "hembra"
}

let perrito = Animal() — Esto es una instancia. Y es obligatorio si queremos modificar cosas, obtener valores, etc. La instancia se crea con el nombre de la clase seguido de unos paréntesis “()”. Esto permite asignar argumentos posteriormente. Más adelante se verá un ejemplo. Finalmente, el valor resultante se le asigna a una constante o variable.

Ahora llegados a este punto, reflexionemos un momento. Quizás, es bueno coger un refresco y tomar un respiro y abrir la mente. Todo esto es raro. Pero, ¿Qué hemos hecho? O, mejor dicho, ¿qué es lo que estamos haciendo? Si hacemos los ejercicios del Playground (Todos) hay un juego, que se trata de dibujar animalitos en una pantalla. Estos animalitos son ranitas, caballitos, etc. en forma de emoticonos. ¿Y cómo trabaja con ellos?, pues mediante instancias:

let animals = [caballo, rana, pez, oveja]
…….código…..
let index = randomInt(from: 0, to: animals.count -1)
var animal = Graphic(image: animals[index])

Pensémoslo, sino tuviéramos una instancia, ¿cómo situaríamos cada uno de los animalitos? Graphic() hace referencia a una clase, que en el juego no vemos, que permite representar en pantalla cada uno de los emoticonos. Luego, los podemos situar en un lugar determinado, separalos más o menos, hacer que giren, se difuminen, etc.

Dicho esto, volvemos al ejercicio del animalito. La constante “perrito” ahora apunta a una instancia de la clase Animal. Con una instancia podemos cambiar sus propiedades. Veamos:

perrito.nombre = "Laika"
perrito.raza = "Galgo"
perrito.sexo = "Hembra"

Esto lo realizamos empleando la sintaxis del punto.

Sin embargo, en el ejemplo anterior, obtenemos un error al asignar “hembra” a la propiedad “sexo”. Este error, nos avisa que sólo las variables pueden modificarse después de realizar una instancia. Las constantes no pueden modificarse. Para ello, tal como hemos dicho anteriormente hay que emplear el “init()”.

El init() y el self

Antes hemos introducido el concepto de inicializador. El inicializador puede aplicarse en una clase o estructura. Un inicializador es un tipo especial de método.

class Animal {
 var nombre: String?
 var raza: String?
 let sexo = "hembra"

init() {
    sexo = "macho"
 }
}

Si nos fijamos la palabra “init” no está precedida por la palabra clave reservada “func”. Luego, con el “init” podemos cambiar una propiedad constante de dos maneras, como arriba se muestra o bien ser más explícitos y hacerlo con la palabra reservada “self”:

init() {
 self.sexo = "macho"
}

El “self” es lo mismo que el “this” en Java y que el “self” en Objective-C. Sin embargo, en Swift sólo se requiere cuando se llama a una propiedad o un método desde una “clousure” o con inicializadores.

Parámetros

Anteriormente hemos visto que es posible enviar parámetros al inicializador. Para ello el “init” es capaz de aceptar uno o varios argumentos. En el siguiente ejemplo, el “init” acepta el argumento de tipo String, llamado “sexo”. Veamos:

init(sexo: String) {
 self.sexo = sexo
}

Lo que está diciendo esto es que la propiedad local o variable sexo, es igual a lo que se le está enviando a través del parámetro. En el siguiente ejemplo, invocamos la clase animal con un argumento llamado “hombre” e imprimimos el resultado de cambiar la propiedad.

let perrito = Animal(sexo: "macho")
println(perrito.sexo) // Outputs "male"

Si observamos, el valor inicial de la propiedad sexo es la constante “hembra”. Con el init() podemos animalizar la propiedad.

Swift admite parámetros con nombre para mejorar la comprensibilidad. El resultado es que el código es mucho más comprensible y más sencillo. Por ejemplo, que el método “insert(_:at:)” inserta un elemento en un determinado índice, con lo que matriz3.insert(«Cebolla», at: 2), significa que en la matriz3 se insertará una cebolla en la posición segunda.

Instancias múltiples

Una clase o estructura en Swift puede tener más de una instancia. En el siguiente ejemplo, creamos dos instancias llamadas Animal. En la primera línea, empleamos el ya conocido. En la segunda línea, empleamos una instancia nueva.

let perrito = Animal()
let perrita = Animal(sexo: "hombre")

Definiendo una Estructura

Las estructuras son tan parecidas a las clases que parecen iguales. Sin embargo, existen ciertas diferencias. Empecemos con una estructura muy básica.

struct cartera {
 var euros: Int
 var centimos: Int

 init() {
    euros = 0
    centimos = 0
  }
}

Inicialmente, pudiera parecer que la principal y única diferencia es el empleo de la palabra clave reservada “struct” en vez de la palabra clave reservada “class”. Otra cosa interesante de este ejemplo, es que mediante el “init” podemos dar unos valores iniciales a las propiedades sin que Swift nos arroje un error, como hacíamos con las clases.

Sin embargo, en el ejemplo anterior no se puede conocer con exactitud la diferencia entre las clases y las estructuras. A primera vista, parecen iguales tanto en forma como en funcionalidad, con la excepción de las palabras clave reservadas de “class” y “struct”. Diferencias:

  • Las estructuras generan automáticamente inicializadores, mientras que en las clases no lo hacen.
  • Las estructuras no soportan herencias, sin embargo, las clases si las soportan.
  • Las estructuras son pasadas por valor mientras que las clases son pasadas por referencia.

Sin embargo, la principal diferencia es que las estructuras son “Value Type” y las clases “Reference Type”. Para entender este concepto veamos este ejemplo:

class cambiarNombre{
 var nombre: String
  Init(nombre: String){
   self.nombre = nombre
  }
}

var clasePrimera = cambiarNombre(nombre: “Yago”)
var claseSegunda = clasePrimera
claseSegunda.nombre = “Pablo”

println(clasePrimera.nombre) //”Pablo”
println(claseSegunda.nombre) //”Pablo”

Sin embargo, veamos que sucede con una estructura:

struct cambiarNombre{
 var nombre: String
  Init(nombre: String){
   self.nombre = nombre
 }
}

var clasePrimera = cambiarNombre(nombre: “Yago”)
var claseSegunda = clasePrimera
claseSegunda.nombre = “Pablo”

println(clasePrimera.nombre) //” Yago”
println(claseSegunda.nombre) //”Pablo”

Aunque no lo veamos en la estructura se generan dos instancias diferentes de la estructura cambiarNombre. Sin embargo, en la clase cambiarNombre la instancia es la misma.

Es complicado decir, cuándo se emplea uno u otro caso. En general, la estructura tiene más sentido en caso que se necesiten copiar o modificar valores fácilmente y calcular con ellos, con menor probabilidad de errores o resultados inesperados.

Copiar objetos

Como acabamos de aprender, una diferencia entre clases y estructuras es la manera en que se copian objetos. No es lo mismo copiar en la clase que en la estructura. Veamos:

class cantante{
 var nombre = “Julio Iglesias”
}

Luego si generamos una instancia de esa clase e imprimimos, obtendremos el nombre de “Julio Iglesias”.

var cantante = cantante()
print(cantante.nombre)

Aquí veremos en consola “Julio Iglesias”.

Ahora crearemos una segunda variable a partir de la primera y cambiaremos su nombre.

var copiarCantante = cantante()
copiarCantante.nombre = “Manuel Serrat”

Por lo que si imprimimos, print(copiarCantante.nombre) será “Manuel Serrat”. Es decir, todo apunta a la variable nombre. Sin embargo, si repetimos lo mismo con una estructura, el resultado sería “Julio Iglesias”.

Herencia

Como hemos indicado, las clases pueden tener herederos mientras que las estructuras no. Para ello, analicemos el siguiente ejemplo:

class Animal {
  var nombre: String?
  var raza: String?
  let sexo = "hembra"

 init(sexo: String) {
    self.sexo = sexo
 }
}

class Especie: Animal {
var nombre: String?
}

let especie = Especie(sexo: "Macho")

En el anterior ejemplo, a la clase Animal se la conoce como clase padre o superclase de la clase Estudiante. Con ello, la clase “Especie” hereda las propiedades y el comportamiento de la clase Animal. Es decir, aunque estemos empleando una clase con un nombre diferente podríamos pensar que es una clase totalmente diferente. Sin embargo, al hacer referencia a Animal(), hereda de ésta.

Conclusión

En este apartado hemos analizado que son las inicializaciones, para que se utilizan, las diferencias entre clases y estructuras. Hemos aprendido lo que son los métodos, objetos, instancias y toda la base fundamental de Swift.

Más información

Si deseas más información sobre cómo programar en Swift consulta en la web oficial de Apple. Para cualquier otra consulta, puedes contactar con nosotros. También nos puedes ayudar descargando nuestra APP de Servicios Profesionales, freelancers y autónomos.

Leave a Comment

Your email address will not be published. Required fields are marked *

Información básica sobre protección de datos
Responsable Francisco de Asís Benavente Delgado +info...
Finalidad Gestionar y moderar tus comentarios. +info...
Legitimación Consentimiento del interesado. +info...
Destinatarios No se cederán datos a terceros, salvo obligación legal +info...
Derechos Acceder, rectificar y cancelar los datos, así como otros derechos. +info...
Información adicional Puedes consultar la información adicional y detallada sobre protección de datos en nuestra página de política de privacidad.