Swift From Scratch una introducción a las clases y estructuras

Hasta ahora, hemos cubierto los conceptos básicos del lenguaje de programación Swift. Si siguió adelante, ahora debería tener una comprensión sólida de variables, constantes, funciones y cierres. Ahora es el momento de utilizar lo que hemos aprendido y aplicar ese conocimiento a las estructuras orientadas a objetos de Swift.

Para comprender los conceptos discutidos en este tutorial, es importante que tenga una comprensión básica de la programación orientada a objetos. Si no está familiarizado con las clases, los objetos y los métodos, le recomiendo que primero lea estos temas antes de continuar con este tutorial..

eBook: Programación Orientada a Objetos Con Swift

1. Introducción

En esta lección, vamos a explorar los bloques de construcción fundamentales de la programación orientada a objetos en Swift, clases y estructuras. En Swift, las clases y las estructuras se sienten y se comportan de manera muy similar, pero hay una serie de diferencias clave que debe comprender para evitar las dificultades comunes..

En Objective-C, las clases y las estructuras son muy diferentes. Esto no es cierto para Swift. En Swift, por ejemplo, tanto las clases como las estructuras pueden tener propiedades y métodos. A diferencia de las estructuras en C, las estructuras en Swift pueden extenderse y también pueden ajustarse a los protocolos.

La pregunta obvia es: "¿Cuál es la diferencia entre clases y estructuras?" Volveremos a examinar esta pregunta más adelante en este tutorial. Primero exploremos cómo se ve una clase en Swift.

2. terminología

Antes de comenzar a trabajar con clases y estructuras, me gustaría aclarar algunos términos comunes en la programación orientada a objetos. Los términos clases, objetos, y instancias A menudo confunden a las personas nuevas con la programación orientada a objetos. Por lo tanto, es importante que sepa cómo Swift usa estos términos..

Objetos e instancias

UNA clase es un plano o plantilla para una instancia de esa clase. El término "objeto" se usa a menudo para referirse a una instancia de una clase. En Swift, sin embargo, las clases y estructuras son muy similares, y por lo tanto es más fácil y menos confuso usar el término "instancia" para ambas clases y estructuras.

Métodos y funciones

Anteriormente en esta serie, trabajamos con funciones. En el contexto de clases y estructuras, generalmente nos referimos a funciones como métodos. En otras palabras, los métodos son funciones que pertenecen a una clase o estructura particular. En el contexto de clases y estructuras, puede usar ambos términos indistintamente ya que cada método es una función.

3. Definiendo una clase

Mojémonos los pies y definamos una clase. Arranca Xcode y crea un nuevo parque infantil. Quite los contenidos del patio de recreo y agregue la siguiente definición de clase.

clase Persona 

los clase palabra clave indica que estamos definiendo una clase llamada Persona. La implementación de la clase está envuelta en un par de llaves. A pesar de Persona La clase no es muy útil en su forma actual, es una clase Swift adecuada y funcional..

Propiedades

Como en la mayoría de los otros lenguajes de programación orientados a objetos, una clase puede tener propiedades y métodos. En el ejemplo actualizado a continuación, definimos tres propiedades:

  • nombre de pila, una propiedad variable de tipo Cuerda?
  • apellido, una propiedad variable de tipo Cuerda?
  • lugar de nacimiento: una propiedad constante de tipo Cuerda
class Person var firstName: String? var lastName: String? let birthPlace = "Belgium"

Como se ilustra en el ejemplo, definir propiedades en una definición de clase es similar a definir variables y constantes regulares. Usamos el var palabra clave para definir una propiedad variable y la dejar palabra clave para definir una propiedad constante.

Las propiedades anteriores también se conocen como propiedades almacenadas. Más adelante en esta serie, aprendemos sobre propiedades computadas. Como su nombre lo indica, las propiedades almacenadas son propiedades almacenadas por la instancia de la clase. Son similares a las propiedades en Objective-C.

Es importante tener en cuenta que cada propiedad almacenada debe tener un valor después de la inicialización o debe definirse como un tipo opcional. En el ejemplo anterior, damos la lugar de nacimiento propiedad un valor inicial de "Bélgica". Esto le dice a Swift que la propiedad del lugar de nacimiento es de tipo Cuerda. Más adelante en este artículo, echamos un vistazo a la inicialización con más detalle y exploramos cómo se relaciona con las propiedades de inicialización..

Aunque definimos la lugar de nacimiento como una constante, es posible cambiar su valor durante la inicialización de un Persona ejemplo. Una vez que la instancia ha sido inicializada, la lugar de nacimiento la propiedad ya no se puede modificar ya que definimos la propiedad como una propiedad constante con el dejar palabra clave.

Métodos

Podemos agregar comportamiento o funcionalidad a una clase a través de funciones o métodos. En muchos lenguajes de programación., método se utiliza en lugar de función En el contexto de las clases e instancias. Definir un método es casi idéntico a definir una función. En el siguiente ejemplo, definimos la nombre completo() método en el Persona clase.

class Person var firstName: String? var lastName: String? let birthPlace = "Belgium" func fullName () -> String var parts: [String] = [] si let firstName = self.firstName parts + = [firstName] si let lastName = self.lastName parts + = [ lastName] return parts.joined (separator: "")

El método nombre completo() Está anidado en la definición de la clase. No acepta parámetros y devuelve un Cuerda. La implementación de la nombre completo() El método es sencillo. A través del enlace opcional, que discutimos anteriormente en esta serie, accedemos a los valores almacenados en el nombre de pila y apellido propiedades.

Almacenamos el nombre y apellido de la Persona Instalar en una matriz y unir las partes con un espacio. El motivo de esta implementación un tanto torpe debe ser obvio: el nombre y el apellido pueden estar en blanco, por lo que ambas propiedades son de tipo Cuerda?.

Instanciación

Hemos definido una clase con algunas propiedades y un método. ¿Cómo creamos una instancia de la Persona ¿clase? Si está familiarizado con Objective-C, entonces le encantará la concisión del siguiente fragmento de código.

dejar que john = persona ()

La creación de una instancia de una clase es muy similar a invocar una función. Para crear una instancia, el nombre de la clase va seguido de un par de paréntesis, y el valor de retorno se asigna a una constante o variable.

En nuestro ejemplo, la constante. Juan Ahora apunta a una instancia de la Persona clase. ¿Significa esto que no podemos cambiar ninguna de sus propiedades? El siguiente ejemplo responde a esta pregunta..

john.firstName = "John" john.lastName = "Doe" john.birthPlace = "France"

Podemos acceder a las propiedades de una instancia utilizando la comodidad de la sintaxis de puntos. En el ejemplo, ponemos nombre de pila a "Juan", apellido a "Gama", y lugar de nacimiento a "Francia". Antes de sacar conclusiones basadas en el ejemplo anterior, debemos comprobar si hay errores en el patio de recreo..

Ajuste nombre de pila y apellido No parece causar ningún problema. Pero asignando "Francia" al lugar de nacimiento La propiedad resulta en un error. La explicacion es simple.

Aunque Juan Se declara como una constante, que no nos impide modificar la Persona ejemplo. Sin embargo, hay una advertencia: solo las propiedades variables se pueden modificar después de inicializar una instancia. Las propiedades que se definen como constantes no se pueden modificar una vez que se asigna un valor.

Una propiedad constante se puede modificar durante la inicialización de una instancia. Mientras que la lugar de nacimiento la propiedad no se puede cambiar una vez que Persona Se crea una instancia, la clase no sería muy útil si solo pudiéramos instanciar Persona Casos con un lugar de nacimiento de "Bélgica". Hagamos el Persona clase un poco más flexible.

Inicialización

La inicialización es una fase en la vida útil de una instancia de una clase o estructura. Durante la inicialización, preparamos la instancia para su uso al rellenar sus propiedades con valores iniciales. La inicialización de una instancia se puede personalizar implementando un inicializador, un tipo especial de método. Vamos a definir un inicializador para el Persona clase.

class Person var firstName: String? var lastName: String? let birthPlace = "Belgium" init () birthPlace = "France"…

Hemos definido un inicializador, pero nos encontramos con varios problemas. Echa un vistazo al error que el compilador nos lanza..

No solo el inicializador no tiene sentido, el compilador también nos advierte que no podemos modificar el valor de lugar de nacimiento Propiedad ya que ya tiene un valor inicial. Podemos resolver el error eliminando el valor inicial de lugar de nacimiento propiedad.

class Person var firstName: String? var lastName: String? let birthPlace: String init () birthPlace = "France"…

Tenga en cuenta que el nombre del inicializador, en eso(), no está precedido por el función palabra clave. A diferencia de los inicializadores en Objective-C, un inicializador en Swift no devuelve la instancia que se está inicializando.

Otro detalle importante es cómo configuramos el lugar de nacimiento Propiedad con un valor inicial. Establecemos el lugar de nacimiento propiedad utilizando el nombre de la propiedad, pero también está bien ser más explícito como este.

init () self.birthPlace = "France"

los yo palabra clave se refiere a la instancia que se está inicializando. Esto significa que self.birthPlace se refiere a lugar de nacimiento Propiedad de la instancia. Podemos omitir yo, como en el primer ejemplo, porque no hay confusión sobre a qué propiedad nos referimos. Sin embargo, este no es siempre el caso. Déjame explicarte a lo que me refiero.

Parámetros

El inicializador que definimos no es muy útil en este momento, y no resuelve el problema con el que empezamos: poder definir el lugar de nacimiento de una persona durante la inicialización. 

En muchas situaciones, desea pasar los valores iniciales al inicializador para personalizar la instancia que está creando. Esto es posible creando un inicializador personalizado que acepte uno o más argumentos. En el siguiente ejemplo, creamos un inicializador personalizado que acepta un argumento, lugar de nacimiento, de tipo Cuerda.

init (birthPlace: String) self.birthPlace = birthPlace

Vale la pena señalar dos cosas. Primero, estamos obligados a acceder a la lugar de nacimiento propiedad a través de self.birthPlace para evitar ambigüedades ya que el nombre del parámetro local es igual a lugar de nacimiento. En segundo lugar, aunque no hemos especificado un nombre de parámetro externo, Swift crea de forma predeterminada un nombre de parámetro externo que es igual al nombre del parámetro local.

En el siguiente ejemplo, instanciamos otra Persona instancia invocando el inicializador personalizado que acabamos de definir.

let maxime = Person (birthPlace: "France") print (maxime.birthPlace)

Al pasar un valor para el lugar de nacimiento parámetro al inicializador, podemos asignar un valor personalizado a la constante lugar de nacimiento propiedad durante la inicialización.

Inicializadores múltiples

Como en Objective-C, una clase o estructura puede tener múltiples inicializadores. En el siguiente ejemplo, creamos dos Persona instancias. En la primera línea, usamos el inicializador por defecto. En la segunda línea, usamos el inicializador personalizado que definimos anteriormente.

dejar p1 = Persona () dejar p2 = Persona (birthPlace: "Francia")

4. Definir una estructura

Las estructuras son sorprendentemente similares a las clases, pero hay algunas diferencias clave. Empecemos definiendo una estructura básica..

struct Wallet var dollars: Int var cents: Int

A primera vista, la única diferencia es el uso del estructura palabra clave en lugar de la clase palabra clave. El ejemplo también nos muestra un enfoque alternativo para suministrar valores iniciales a propiedades. En lugar de establecer un valor inicial para cada propiedad, podemos asignar a las propiedades un valor inicial en el inicializador de la estructura. Swift no generará un error, ya que también inspecciona el inicializador para determinar el valor inicial y el tipo de cada propiedad.

5. Clases y estructuras

Puede comenzar a preguntarse cuál es la diferencia entre clases y estructuras. A primera vista, se ven idénticos en forma y función, con la excepción de la clase y estructura palabras clave. Hay una serie de diferencias clave, aunque.

Herencia

Las clases apoyan la herencia, mientras que las estructuras no lo hacen. El siguiente ejemplo lo ilustra. El patrón de diseño de herencia es indispensable en la programación orientada a objetos y, en Swift, es una diferencia clave entre clases y estructuras..

class Person var firstName: String? var lastName: String? let birthPlace: String init (birthPlace: String) self.birthPlace = birthPlace class Estudiante: Persona var school: String?  let student = Student (birthPlace: "France")

En el ejemplo anterior, el Persona clase es el padre o superclase de la Estudiante clase. Esto significa que el Estudiante clase hereda las propiedades y el comportamiento de la Persona clase. La última línea ilustra esto. Inicializamos un Estudiante instancia invocando el inicializador personalizado definido en el Persona clase.

Copiando y referenciando

El siguiente concepto es probablemente el concepto más importante en Swift que aprenderá hoy, la diferencia entre tipos de valor y tipos de referencia. Las estructuras son tipos de valor, lo que significa que se pasan por valor. Un ejemplo ilustra mejor este concepto..

estructura Punto var x: Int var y: Int init (x: Int, y: Int) self.x = x self.y = y var point1 = Point (x: 0, y: 0) var point2 = point1 point1.x = 10 print (point1.x) // 10 print (point2.x) // 0

Definimos una estructura., Punto, para encapsular los datos para almacenar una coordenada en un espacio bidimensional. Nosotros instanciamos punto 1 con X igual a 0 y y igual a 0. Asignamos punto 1 a punto2 y establecer el X coordenada de punto 1 a 10. Si sacamos el X Coordenadas de ambos puntos, descubrimos que no son iguales..

Las estructuras se pasan por valor, mientras que las clases se pasan por referencia. Si planea continuar trabajando con Swift, debe comprender la declaración anterior. Cuando asignamos punto 1 a punto2, Swift creó una copia de punto 1 y asignado a punto2. En otras palabras, punto 1 y punto2 cada punto a una instancia diferente de la Punto estructura.

Repitamos ahora este ejercicio con la Persona clase. En el siguiente ejemplo, creamos una instancia de Persona instancia, establecer sus propiedades, asignar persona1 a persona2, y actualizar el nombre de pila propiedad de persona1. Para ver lo que significa pasar por referencia para las clases, generamos el valor de nombre de pila propiedad de ambos Persona instancias.

var person1 = Persona (birthPlace: "Belgium") person1.firstName = "Jane" person1.lastName = "Doe" var person2 = person1 person1.firstName = "Janine" print (person1.firstName!) // Janine print (person2. primer nombre!) // Janine

El ejemplo demuestra que las clases son tipos de referencia. Esto significa que persona1persona2 referirse o referirse al mismo Persona ejemplo. Asignando persona1persona2, Swift no crea una copia de persona1. los persona2 variable puntos al mismo Persona ejemplo persona1 está apuntando a Cambiando el nombre de pila propiedad de persona1 también afecta a la nombre de pila propiedad de persona2, porque están haciendo referencia a la misma Persona ejemplo.

Como mencioné varias veces en este artículo, las clases y estructuras son muy similares. Lo que separa clases y estructuras es muy importante. Si los conceptos anteriores no son claros, lo invito a leer el artículo una vez más para dejar que los conceptos que cubrimos se hundan..

Conclusión

En esta entrega de Swift From Scratch, comenzamos a explorar los conceptos básicos de la programación orientada a objetos en Swift. Las clases y estructuras son los componentes fundamentales de la mayoría de los proyectos Swift, y aprenderemos más sobre ellos en las próximas lecciones de esta serie..

En la siguiente lección, continuamos nuestra exploración de clases y estructuras al observar más de cerca las propiedades y la herencia..

Si desea aprender a usar Swift 3 para codificar aplicaciones del mundo real, consulte nuestro curso Crear aplicaciones de iOS con Swift 3. Ya sea que sea nuevo en el desarrollo de aplicaciones de iOS o desee cambiar de Objective-C, este El curso te ayudará a comenzar con Swift para el desarrollo de aplicaciones..