Ahora que Apple ha lanzado oficialmente Xcode 6 y se ha levantado el NDA, es hora de profundizar en Swift, el nuevo lenguaje de Apple para crear aplicaciones iOS. Aprender a utilizar correctamente los inicializadores en Swift puede resultar abrumador al principio. El requisito de Swift de que todas las propiedades almacenadas en una clase estén inicializadas agrega complejidad al proceso de inicialización. En la primera parte de esta publicación de dos partes, voy a desmitificar los inicializadores mientras proporciono un enfoque práctico para aprender cómo implementar mejor los inicializadores en sus clases personalizadas.
Cuando crea sus propias clases personalizadas en Swift, debe asegurarse de que los nuevos objetos instanciados de su clase personalizada estén correctamente inicializados (listos para usarse). Esto generalmente implica asegurarse de que todas las propiedades almacenadas tengan un valor inicial, así como cualquier otra configuración especializada que su clase pueda requerir.
En Swift, todas las propiedades almacenadas deben inicializarse. No se les permite estar en un estado desconocido. Hay dos formas principales de almacenar un valor inicial en una propiedad:
- En la declaración de propiedad – Por ejemplo:
- En un inicializador – Por ejemplo:
En situaciones donde el valor inicial de la propiedad es siempre el mismo, debe elegir la primera opción e inicializar el valor en la declaración de propiedad. Esto vincula estrechamente la inicialización de la propiedad con su declaración, lo que hace que su código sea más intuitivo.
En los casos en que cambie el valor inicial de una propiedad, debe elegir un inicializador en su lugar.
Índice de contenido
Inicialización e inferencia de tipos
Si almacena un valor inicial en la declaración de una propiedad, no necesita especificar el tipo de propiedad porque Swift puede averiguarlo o inferir su tipo en función del tipo de valor que está almacenando en la propiedad.
Sin embargo, si establece el valor inicial de una propiedad en un inicializador, debe especificar el tipo de propiedad cuando la declare.
Crear inicializadores
Estas son algunas de las reglas básicas que rigen los inicializadores:
- Los inicializadores en Swift siempre se nombran en eso.
- No usas el func palabra clave al declarar un inicializador.
- Los inicializadores no devuelven un valor.
- Puede crear varios inicializadores para una sola clase que acepten diferentes parámetros.
- Si su clase tiene una superclase, debe llamar a uno de sus inicializadores designados desde su inicializador personalizado (más sobre eso en un momento).
Parámetros del inicializador
Puede crear varios métodos de inicialización para su clase personalizada que proporcionen a los consumidores de su clase una variedad de formas de inicializar objetos.
Si tiene una clase que requiere que el desarrollador de la aplicación establezca propiedades específicas, debe crear uno o más inicializadores que permitan que esos valores se pasen en la inicialización. Esto ayuda a que su clase se documente por sí misma.
Para ayudarlo a comprender mejor cómo funcionan los inicializadores, creemos un Traductor cuyo propósito es traducir frases de un idioma a otro (esto solo será una maqueta). Primero crearemos la clase sin inicializadores, y luego la mejoraremos agregando un inicializador con parámetros.
Para seguir estas instrucciones paso a paso, descargue el InitializerDemo proyecto de muestra de este enlace.
- Abre el InitializerDemo proyecto ubicado en la carpeta donde lo ha descargado.
- Haga clic derecho en el InitializerDemo grupo y luego seleccione Archivo nuevo… en el menú emergente.
- En el lado izquierdo del cuadro de diálogo Crear archivo debajo del iOS sección, seleccione Fuente.
- En el lado derecho del cuadro de diálogo, seleccione el Archivo Swift plantilla y luego haga clic en Próximo.
- En el cuadro de diálogo Guardar archivo, cambie el Nombre del archivo a Translator.swifty luego haga clic en el Crear botón Esto agrega el Translator.swift archivo al proyecto.
- Agregue la siguiente declaración de enumeración en la parte superior del archivo debajo del Fundación de importación declaración:
Esta enumeración declara todos los idiomas que admite la clase Translator.
- Ahora agregue la siguiente declaración de clase debajo de la declaración de enumeración:
En este ejemplo, el propósito principal del Traductor La clase consiste en traducir frases de un idioma a otro. No puede realizar ninguna transacción sin conocer los idiomas “desde” y “hasta”. sin embargo, el fromLanguage y toLanguage las propiedades están marcadas como opcionales. Desde una perspectiva práctica, son cualquier cosa pero ¡Opcional!
Nota: No es necesario establecer explícitamente las propiedades opcionales en nil, ¡pero hice esto para solucionar un error con el compilador Swift!
- Intentemos crear una instancia de esta clase a partir de una prueba unitaria. Para hacer esto, con el Translator.swift archivo seleccionado en el Navegador de proyectos, vaya al Inspector de archivos (el primer botón a la izquierda en la barra de herramientas del Inspector) y seleccione el InitializerDemoTests casilla de verificación como se muestra en Figura 1. Esto hace que la clase sea accesible para el proyecto de prueba unitaria.
Figura 1 – Seleccione la membresía de destino de InitializerDemoTests |
- Bajo la InitializerDemoTests en el Navegador de proyectos, seleccione el InitializerDemoTests.swift expediente.
- Agregue el siguiente método de prueba al final del archivo de código sobre la llave de cierre de la clase:
Este es un mal diseño porque requiere que el desarrollador averigüe por sí mismo que el fromLanguage y toLanguage las propiedades deben establecerse antes de Traductor se puede utilizar el objeto.
Creemos un mejor diseño.
- Vuelve al Traductor clase y quitar el ? = nada después de la Idioma escriba para indicar que estas propiedades no son opcionales. Luego, cambie el inicializador como se muestra aquí:
Esta clase ahora tiene un único inicializador con desde y a parámetros de tipo Idioma.
- Prensa Comando + B para construir el proyecto. Ahora debería tener un error de compilador. Para ver qué está causando el problema, seleccione el InitializerDemoTests.swift archivo en el Navegador de proyectos y debería ver el error que se muestra en Figura 2.
Figura 2 – El error del compilador “Falta un argumento” |
El texto completo del error indica “Falta un argumento del parámetro ‘de’ en la llamada”. ¿Por qué recibe este error?
Si no especifica un inicializador personalizado para una clase, entre bastidores, el compilador Swift agrega un inicializador predeterminado. Es por eso que falla el código en la prueba unitaria que intenta usar este inicializador predeterminado.
En nuestro ejemplo, ¡esto es exactamente lo que queremos! Queremos obligar a los desarrolladores a pasar los dos necesarios Idioma valores cuando crean una instancia de la clase. Cambiemos el código para hacer eso ahora.
- Primero, elimine todo el código dentro del testTranslator método. Luego, agregue el siguiente código:
Cuando escribe el paréntesis de la izquierda, aparece Completación de código que ofrece la opción que se muestra en figura 3.
Figura 3 – Finalización de código para el inicializador personalizado |
Esto deja muy claro para los desarrolladores que deben especificar los idiomas “desde” y “hasta” al crear una instancia del Traductor clase.
- Con la plantilla de finalización de código mostrada (si no está visible, presione escapar para volver a mostrarlo), presione pestaña moverse a la desde marcador de posición y tipo Idioma: inglés. Prensa pestaña una segunda vez para pasar a la marcador de posición y entrar Idioma chino. Luego, presione la tecla de flecha derecha para que Swift complete automáticamente los paréntesis de cierre. Cuando haya terminado, su código debería verse así:
Como puede ver, Code Completion inserta los nombres de los parámetros en la llamada al método. Esto es obligatorio. Si omite estos nombres de parámetros, obtendrá un error del compilador.
Esta no es una verdadera prueba unitaria, pero quería que experimentara la llamada a diferentes tipos de inicializadores.
Nombres de parámetros locales y externos
Los nombres de los parámetros locales y externos funcionan un poco diferente para los inicializadores que para los métodos normales.
Dado que un inicializador siempre se llama en eso, no puede darse el lujo de crear un nombre de inicializador que incluya una descripción del primer parámetro. Debido a esto, Swift proporciona un nombre externo automático que es el mismo que el nombre local para cada parámetro que declara, como se puede ver en figura 3.
Si desea declarar un nombre externo que sea diferente al nombre local, use la misma sintaxis que con los métodos Swift normales. Por ejemplo, el siguiente código declara un nombre externo diferente para el desde y a nombres de parámetros locales:
En este ejemplo, la declaración de nombres de parámetros externos cambia los nombres de los parámetros cuando llama al inicializador como se muestra en Figura 4.
Figura 4 – Los nuevos nombres de parámetros externos en acción |
Si no desea proporcionar un nombre externo para un parámetro, simplemente inserte un guión bajo antes del nombre del parámetro local.
Inicializadores designados y de conveniencia
Swift admite dos tipos principales de inicializadores: inicializadores designados e inicializadores de conveniencia. Echemos un vistazo más de cerca a cada uno para que pueda aprender la mejor manera de inicializar sus clases personalizadas.
Inicializadores designados
A inicializador designado es el inicializador principal de una clase. Inicializa todas las propiedades declaradas en la clase y es responsable de llamar a un inicializador en su superclase (si tiene una superclase).
Por ejemplo, en el Traductor clase, init: desde: hasta: es el inicializador designado porque inicializa ambas propiedades declaradas en la clase.
Aquí está la sintaxis de un inicializador designado:
Cada clase debe tener al menos un inicializador designado. Puede tener más de uno, pero es más común tener solo uno.
Inicializadores de conveniencia
A inicializador de conveniencia es un inicializador de clase secundaria que normalmente acepta menos parámetros que un inicializador designado, pero luego llama al inicializador designado con valores predeterminados establecidos para algunos de los parámetros. Los inicializadores de conveniencia son opcionales, pero a menudo facilitan la creación de instancias de sus clases.
Aquí está la sintaxis de un inicializador de conveniencia:
Creemos un inicializador de conveniencia para que pueda comprender más claramente cómo funcionan.
- En el InitializerDemo proyecto, seleccione el Translator.swift archivo en el Navegador de proyectos.
- Agregue el siguiente inicializador nuevo al Traductor clase:
Aquí hay algunos puntos importantes a tener en cuenta:
- los conveniencia La palabra clave se utiliza para marcar el método como inicializador de conveniencia.
- El inicializador de conveniencia llama al inicializador designado en la misma clase, pasando un Idioma: inglés valor como primer parámetro y pasando por su propio toLanguage parámetro como segundo parámetro.
- El inicializador de conveniencia le permite crear una instancia de la clase pasando solo un parámetro al inicializador. Por ejemplo:
- Cuando crea una instancia de la clase, Code Completion ahora enumera ambos inicializadores como se muestra en Figura 5.
Figura 5 – Múltiples inicializadores en finalización de código |
Conclusión
Esta publicación cubre lo esencial de los inicializadores en Swift, ¡y hay mucho más que aprender! En mi próxima publicación, discutiré los temas “Encadenamiento de inicializadores”, “Inicialización de dos fases” y “Herencia de inicializadores”. ¡Manténganse al tanto!