Swift - Guía rápida
Swift 4 es un nuevo lenguaje de programación desarrollado por Apple Inc para el desarrollo de iOS y OS X. Swift 4 adopta lo mejor de C y Objective-C, sin las limitaciones de la compatibilidad con C.
Swift 4 utiliza patrones de programación seguros.
Swift 4 ofrece funciones de programación modernas.
Swift 4 proporciona una sintaxis similar a Objective-C.
Swift 4 es una forma fantástica de escribir aplicaciones iOS y OS X.
Swift 4 proporciona un acceso perfecto a los marcos Cocoa existentes.
Swift 4 unifica las partes procedimentales y orientadas a objetos del lenguaje.
Swift 4 no necesita una importación de biblioteca separada para admitir funcionalidades como entrada / salida o manejo de cadenas.
Swift 4 usa el mismo tiempo de ejecución que el sistema Obj-C existente en Mac OS e iOS, lo que permite que los programas Swift 4 se ejecuten en muchas plataformas iOS 6 y OS X 10.8 existentes.
Swift 4 viene con una función de área de juegos donde los programadores de Swift 4 pueden escribir su código y ejecutarlo para ver los resultados de inmediato.
El primer lanzamiento público de Swift se lanzó en 2010. Se necesitó Chris Lattnercasi 14 años para llegar a la primera versión oficial, y más tarde, fue apoyada por muchos otros colaboradores. Swift 4 se ha incluido en Xcode 6 beta.
Los diseñadores de Swift tomaron ideas de varios otros lenguajes populares como Objective-C, Rust, Haskell, Ruby, Python, C # y CLU.
Configuración del entorno local
Swift 4 proporciona una plataforma de juegos con fines de aprendizaje y vamos a configurar la misma. Necesita el software xCode para iniciar su codificación Swift 4 en Playground. Una vez que se sienta cómodo con los conceptos de Swift 4, puede usar xCode IDE para el desarrollo de aplicaciones iOS / OS x.
Para empezar, consideramos que ya tiene una cuenta en el sitio web de desarrolladores de Apple. Una vez que haya iniciado sesión, vaya al siguiente enlace: Descargar para desarrolladores de Apple
Esto mostrará una lista de software disponible de la siguiente manera:
Ahora seleccione xCode y descárguelo haciendo clic en el enlace proporcionado cerca de la imagen del disco. Después de descargar el archivo dmg, puede instalarlo simplemente haciendo doble clic en él y siguiendo las instrucciones dadas. Finalmente, siga las instrucciones dadas y suelte el icono de xCode en la carpeta de la Aplicación.
Ahora tiene xCode instalado en su máquina. A continuación, abra Xcode desde la carpeta de la Aplicación y continúe después de aceptar los términos y condiciones. Si todo está bien, aparecerá la siguiente pantalla:
Seleccione Get started with a playgroundopción e ingrese un nombre para el área de juegos y seleccione iOS como plataforma. Finalmente, obtendrá la ventana del patio de juegos de la siguiente manera:
A continuación se muestra el código tomado de la ventana Swift 4 Playground predeterminada.
import UIKit
var str = "Hello, playground"
Si crea el mismo programa para el programa OS X, incluirá import Cocoa y el programa se verá de la siguiente manera:
import Cocoa
var str = "Hello, playground"
Cuando se carga el programa anterior, debería mostrar el siguiente resultado en el área de resultados del Patio de juegos (lado derecho).
Hello, playground
Felicitaciones, tiene listo su entorno de programación Swift 4 y puede continuar con su vehículo de aprendizaje "Tutorials Point".
Ya hemos visto una parte del programa Swift 4 mientras configuramos el entorno. Comencemos una vez más con lo siguienteHello, World! programa creado para el patio de juegos de OS X, que incluye import Cocoa como se muestra a continuación -
/* My first program in Swift 4 */
var myString = "Hello, World!"
print(myString)
Si crea el mismo programa para el patio de juegos de iOS, incluirá import UIKit y el programa se verá de la siguiente manera:
import UIKit
var myString = "Hello, World!"
print(myString)
Cuando ejecutamos el programa anterior usando un patio de recreo apropiado, obtendremos el siguiente resultado:
Hello, World!
Veamos ahora la estructura básica de un programa Swift 4, de modo que le resulte fácil comprender los componentes básicos del lenguaje de programación Swift 4.
Importar en Swift 4
Puedes usar el importdeclaración para importar cualquier marco Objective-C (o biblioteca C) directamente a su programa Swift 4. Por ejemplo, lo anteriorimport cocoa declaración hace que todas las bibliotecas, API y tiempos de ejecución de Cocoa que forman la capa de desarrollo para todo OS X, estén disponibles en Swift 4.
Cocoa está implementado en Objective-C, que es un superconjunto de C, por lo que es fácil mezclar C e incluso C ++ en sus aplicaciones Swift 4.
Fichas en Swift 4
Un programa Swift 4 consta de varios tokens y un token es una palabra clave, un identificador, una constante, una cadena literal o un símbolo. Por ejemplo, la siguiente declaración de Swift 4 consta de tres tokens:
print("test!")
The individual tokens are:
print("test!")
Comentarios
Los comentarios son como textos de ayuda en su programa Swift 4. El compilador los ignora. Los comentarios de varias líneas comienzan con / * y terminan con los caracteres * / como se muestra a continuación -
/* My first program in Swift 4 */
Los comentarios de varias líneas se pueden anidar en Swift 4. A continuación, se muestra un comentario válido en Swift 4:
/* My first program in Swift 4 is Hello, World!
/* Where as second program is Hello, Swift 4! */ */
Los comentarios de una sola línea se escriben utilizando // al principio del comentario.
// My first program in Swift 4
Punto y coma
Swift 4 no requiere que escriba un punto y coma (;) después de cada declaración en su código, aunque es opcional; y si usa un punto y coma, el compilador no se queja.
Sin embargo, si está utilizando varias declaraciones en la misma línea, entonces es necesario utilizar un punto y coma como delimitador, de lo contrario, el compilador generará un error de sintaxis. Puede escribir lo anterior ¡Hola, mundo! programe de la siguiente manera -
/* My first program in Swift 4 */
var myString = "Hello, World!"; print(myString)
Identificadores
Un identificador de Swift 4 es un nombre que se utiliza para identificar una variable, función o cualquier otro elemento definido por el usuario. Un identificador comienza con un alfabeto de la A a la Z o de la aa la z o un guión bajo _ seguido de cero o más letras, guiones bajos y dígitos (0 a 9).
Swift 4 no permite caracteres especiales como @, $ y% dentro de los identificadores. Swift 4 es uncase sensitivelenguaje de programación. Por lo tanto, Manpower y manpower son dos identificadores diferentes en Swift 4. A continuación, se muestran algunos ejemplos de identificadores aceptables:
Azad zara abc move_name a_123
myname50 _temp j a23b9 retVal
Para usar una palabra reservada como identificador, deberá poner una tilde (`) antes y después de ella. Por ejemplo,class no es un identificador válido, pero `class`es válido.
Palabras clave
Las siguientes palabras clave están reservadas en Swift 4. Estas palabras reservadas no se pueden usar como constantes o variables o cualquier otro nombre de identificador, a menos que se escapen con comillas invertidas:
Palabras clave utilizadas en declaraciones
Clase | deinit | Enum | extensión |
Func | importar | En eso | interno |
Dejar | operador | privado | protocolo |
público | estático | estructura | subíndice |
typealias | var |
Palabras clave utilizadas en declaraciones
romper | caso | Seguir | defecto |
hacer | más | caer a través | para |
Si | en | regreso | cambiar |
dónde | mientras |
Palabras clave utilizadas en expresiones y tipos
como | dynamicType | falso | es |
nulo | yo | Yo | súper |
cierto | _COLUMNA_ | _ARCHIVO_ | _FUNCIÓN_ |
_LÍNEA_ |
Palabras clave utilizadas en contextos particulares
asociatividad | conveniencia | dinámica | didSet |
final | obtener | infijo | En fuera |
perezoso | izquierda | mutante | ninguna |
no mutante | Opcional | anular | sufijo |
precedencia | prefijo | Protocolo | necesario |
derecho | conjunto | Tipo | sin propietario |
débiles | establecerá |
Espacios en blanco
Una línea que contiene solo espacios en blanco, posiblemente con un comentario, se conoce como línea en blanco, y un compilador de Swift 4 la ignora por completo.
Espacio en blanco es el término utilizado en Swift 4 para describir espacios en blanco, tabulaciones, caracteres de nueva línea y comentarios. Los espacios en blanco separan una parte de una declaración de otra y permiten al compilador identificar dónde termina un elemento de una declaración, como int, y comienza el siguiente. Por lo tanto, en la siguiente declaración:
var age
Debe haber al menos un carácter de espacio en blanco (generalmente un espacio) entre var y agepara que el compilador pueda distinguirlos. Por otro lado, en la siguiente declaración:
int fruit = apples + oranges //get the total fruits
No se necesitan espacios en blanco entre frutas y =, o entre = y manzanas, aunque puede incluir algunos para una mejor legibilidad.
El espacio a ambos lados de un operador debe ser igual, por ejemplo.
int fruit = apples +oranges //is a wrong statement
int fruit = apples + oranges //is a Correct statement
Literales
Un literal es la representación del código fuente de un valor de un entero, un número de punto flotante o un tipo de cadena. Los siguientes son ejemplos de literales:
92 // Integer literal
4.24159 // Floating-point literal
"Hello, World!" // String literal
Imprimir en Swift
Para imprimir cualquier cosa en Swift, tenemos la palabra clave 'imprimir'.
La impresión tiene tres propiedades diferentes.
Items - Elementos a imprimir
Separator - separador entre elementos
Terminator - el valor con el que debe terminar la línea, veamos un ejemplo y sintaxis de la misma.
print("Items to print", separator: "Value " , terminator: "Value")
// E.g. of print statement.
print("Value one")
// prints "Value one \n" Adds, \n as terminator and " " as separator by
default.
print("Value one","Value two", separator: " Next Value" , terminator: " End")
//prints "Value one Next Value Value two End"
En el código anterior, la primera declaración de impresión agrega \ n, nueva línea Feed como terminador por defecto, mientras que en la segunda declaración de impresión hemos dado "End" como terminador, por lo que imprimirá "End" en lugar de \ n.
Podemos ofrecer nuestros separadores y terminadores personalizados de acuerdo con nuestros requisitos.
Al programar en cualquier lenguaje de programación, debe utilizar diferentes tipos de variables para almacenar información. Las variables no son más que ubicaciones de memoria reservadas para almacenar valores. Esto significa que cuando crea una variable, reserva algo de espacio en la memoria.
Es posible que desee almacenar información de varios tipos de datos como cadena, carácter, carácter ancho, entero, punto flotante, booleano, etc. Según el tipo de datos de una variable, el sistema operativo asigna memoria y decide qué se puede almacenar en el reservado. memoria.
Tipos de datos integrados
Swift 4 ofrece al programador una amplia variedad de tipos de datos integrados y definidos por el usuario. Los siguientes tipos de tipos de datos básicos son los más frecuentes al declarar variables:
Int or UInt- Esto se usa para números enteros. Más específicamente, puede usar Int32, Int64 para definir enteros con signo de 32 o 64 bits, mientras que UInt32 o UInt64 para definir variables enteras sin signo de 32 o 64 bits. Por ejemplo, 42 y -23.
Float- Se utiliza para representar un número de coma flotante de 32 bits y números con puntos decimales más pequeños. Por ejemplo, 3.14159, 0.1 y -273.158.
Double- Se utiliza para representar un número de punto flotante de 64 bits y se utiliza cuando los valores de punto flotante deben ser muy grandes. Por ejemplo, 3.14159, 0.1 y -273.158.
Bool - Esto representa un valor booleano que es verdadero o falso.
String- Esta es una colección ordenada de personajes. Por ejemplo, "¡Hola, mundo!"
Character- Este es un literal de cadena de un solo carácter. Por ejemplo, "C"
Optional - Esto representa una variable que puede contener un valor o ningún valor.
Tuples - Esto se utiliza para agrupar varios valores en un solo valor compuesto.
Hemos enumerado aquí algunos puntos importantes relacionados con los tipos de números enteros:
En una plataforma de 32 bits, Int tiene el mismo tamaño que Int32.
En una plataforma de 64 bits, Int tiene el mismo tamaño que Int64.
En una plataforma de 32 bits, UInt tiene el mismo tamaño que UInt32.
En una plataforma de 64 bits, UInt tiene el mismo tamaño que UInt64.
Int8, Int16, Int32, Int64 se pueden utilizar para representar formas de entero con signo de 8 bits, 16 bits, 32 bits y 64 bits.
UInt8, UInt16, UInt32 y UInt64 se pueden utilizar para representar formas de entero sin signo de 8 bits, 16 bits, 32 bits y 64 bits.
Valores vinculados
La siguiente tabla muestra el tipo de variable, cuánta memoria se necesita para almacenar el valor en memoria, y cuál es el valor máximo y mínimo que se puede almacenar en ese tipo de variables.
Tipo | Ancho típico de la broca | Rango típico |
---|---|---|
Int8 | 1 byte | -127 hasta 127 |
UInt8 | 1 byte | 0 hasta 255 |
Int32 | 4 bytes | -2147483648 al 2147483647 |
UInt32 | 4 bytes | 0 hasta 4294967295 |
Int64 | 8 bytes | -9223372036854775808 al 9223372036854775807 |
UInt64 | 8 bytes | 0 a 18446744073709551615 |
Flotador | 4 bytes | 1.2E-38 a 3.4E + 38 (~ 6 dígitos) |
Doble | 8 bytes | 2.3E-308 a 1.7E + 308 (~ 15 dígitos) |
Alias de tipo
Puede crear un nuevo nombre para un tipo existente usando typealias. Aquí está la sintaxis simple para definir un nuevo tipo usando typealias:
typealias newname = type
Por ejemplo, la siguiente línea le indica al compilador que Feet es otro nombre para Int -
typealias Feet = Int
Ahora, la siguiente declaración es perfectamente legal y crea una variable entera llamada distancia:
typealias Feet = Int
var distance: Feet = 100
print(distance)
Cuando ejecutamos el programa anterior usando playground, obtenemos el siguiente resultado.
100
Tipo de seguridad
Swift 4 es un lenguaje de tipo seguro, lo que significa que si una parte de su código espera un String, no puede pasarle un Int por error.
Como Swift 4 es de tipo seguro, realiza comprobaciones de tipo al compilar su código y marca cualquier tipo no coincidente como error.
var varA = 42
varA = "This is hello"
print(varA)
Cuando compilamos el programa anterior, produce el siguiente error de tiempo de compilación.
main.swift:2:8: error: cannot assign value of type 'String' to type 'Int'
varA = "This is hello"
Inferencia de tipo
La inferencia de tipos permite a un compilador deducir el tipo de una expresión en particular automáticamente cuando compila su código, simplemente examinando los valores que usted proporciona. Swift 4 usa la inferencia de tipos para calcular el tipo apropiado de la siguiente manera.
// varA is inferred to be of type Int
var varA = 42
print(varA)
// varB is inferred to be of type Double
var varB = 3.14159
print(varB)
// varC is also inferred to be of type Double
var varC = 3 + 0.14159
print(varC)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
42
3.14159
3.14159
Una variable nos proporciona un almacenamiento con nombre que nuestros programas pueden manipular. Cada variable en Swift 4 tiene un tipo específico, que determina el tamaño y el diseño de la memoria de la variable; el rango de valores que se pueden almacenar dentro de esa memoria; y el conjunto de operaciones que se pueden aplicar a la variable.
Swift 4 admite los siguientes tipos básicos de variables:
Int or UInt- Esto se usa para números enteros. Más específicamente, puede usar Int32, Int64 para definir enteros con signo de 32 o 64 bits, mientras que UInt32 o UInt64 para definir variables enteras sin signo de 32 o 64 bits. Por ejemplo, 42 y -23.
Float- Se utiliza para representar un número de coma flotante de 32 bits. Se utiliza para contener números con puntos decimales más pequeños. Por ejemplo, 3.14159, 0.1 y -273.158.
Double- Se utiliza para representar un número de punto flotante de 64 bits y se utiliza cuando los valores de punto flotante deben ser muy grandes. Por ejemplo, 3.14159, 0.1 y -273.158.
Bool - Esto representa un valor booleano que es verdadero o falso.
String- Esta es una colección ordenada de personajes. Por ejemplo, "¡Hola, mundo!"
Character- Este es un literal de cadena de un solo carácter. Por ejemplo, "C"
Swift 4 también permite definir varios otros tipos de variables, que cubriremos en capítulos posteriores, como Optional, Array, Dictionaries, Structures, y Classes.
La siguiente sección cubrirá cómo declarar y usar varios tipos de variables en la programación de Swift 4.
Declaración de variable
Una declaración de variable le dice al compilador dónde y cuánto crear el almacenamiento para la variable. Antes de usar variables, debe declararlas usandovar palabra clave de la siguiente manera:
var variableName = <initial value>
El siguiente ejemplo muestra cómo declarar una variable en Swift 4:
var varA = 42
print(varA)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
42
Tipo de anotaciones
Puede proporcionar un type annotationcuando declara una variable, para tener claro el tipo de valores que la variable puede almacenar. Aquí está la sintaxis:
var variableName:<data type> = <optional initial value>
El siguiente ejemplo muestra cómo declarar una variable en Swift 4 usando Anotación. Aquí es importante tener en cuenta que si no estamos usando la anotación de tipo, entonces es obligatorio proporcionar un valor inicial para la variable; de lo contrario, podemos simplemente declarar nuestra variable usando la anotación de tipo.
var varA = 42
print(varA)
var varB:Float
varB = 3.14159
print(varB)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
42
3.1415901184082
Nombrar variables
El nombre de una variable puede estar compuesto por letras, dígitos y el carácter de subrayado. Debe comenzar con una letra o un guión bajo. Las letras mayúsculas y minúsculas son distintas porque Swift 4 es un lenguaje de programación que distingue entre mayúsculas y minúsculas.
Puede usar caracteres simples o Unicode para nombrar sus variables. Los siguientes ejemplos muestran cómo puede nombrar las variables:
var _var = "Hello, Swift 4!"
print(_var)
var 你好 = "你好世界"
print(你好)
Cuando ejecutamos el programa anterior usando playground, obtenemos el siguiente resultado.
Hello, Swift 4!
你好世界
Impresión de variables
Puede imprimir el valor actual de una constante o variable con la función de impresión. Puede interpolar un valor de variable envolviendo el nombre entre paréntesis y escapando con una barra invertida antes del paréntesis de apertura: A continuación se muestran ejemplos válidos:
var varA = "Godzilla"
var varB = 1000.00
print("Value of \(varA) is more than \(varB) millions")
Cuando ejecutamos el programa anterior usando playground, obtenemos el siguiente resultado.
Value of Godzilla is more than 1000.0 millions
Swift 4 también presenta Optionalstype, que maneja la ausencia de un valor. Los opcionales dicen "hay un valor y es igual a x" o "no hay ningún valor".
Un Opcional es un tipo en sí mismo, en realidad una de las nuevas enumeraciones superpoderosas de Swift 4. Tiene dos valores posibles,None y Some(T), dónde T es un valor asociado del tipo de datos correcto disponible en Swift 4.
Aquí hay una declaración Integer opcional:
var perhapsInt: Int?
Aquí hay una declaración de cadena opcional:
var perhapsStr: String?
La declaración anterior es equivalente a inicializarla explícitamente a nil lo que significa que no tiene valor -
var perhapsStr: String? = nil
Tomemos el siguiente ejemplo para comprender cómo funcionan las opciones en Swift 4:
var myString:String? = nil
if myString != nil {
print(myString)
} else {
print("myString has nil value")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
myString has nil value
Los opcionales son similares a usar nil con punteros en Objective-C, pero funcionan para cualquier tipo, no solo para clases.
Desenvolver forzado
Si definió una variable como optional, luego para obtener el valor de esta variable, tendrá que unwrapeso. Esto solo significa poner un signo de exclamación al final de la variable.
Tomemos un ejemplo simple:
var myString:String?
myString = "Hello, Swift 4!"
if myString != nil {
print(myString)
} else {
print("myString has nil value")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Optional("Hello, Swift 4!")
Ahora apliquemos el desenvolvimiento para obtener el valor correcto de la variable:
var myString:String?
myString = "Hello, Swift 4!"
if myString != nil {
print( myString! )
} else {
print("myString has nil value")
}
Cuando ejecutamos el programa anterior usando playground, obtenemos el siguiente resultado.
Hello, Swift 4!
Desenvasado automático
Puede declarar variables opcionales utilizando un signo de exclamación en lugar de un signo de interrogación. Dichas variables opcionales se desenvolverán automáticamente y no es necesario utilizar ningún otro signo de exclamación al final de la variable para obtener el valor asignado. Tomemos un ejemplo simple:
var myString:String!
myString = "Hello, Swift 4!"
if myString != nil {
print(myString)
} else {
print("myString has nil value")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Hello, Swift 4!
Encuadernación opcional
Utilice el enlace opcional para averiguar si un opcional contiene un valor y, de ser así, para que ese valor esté disponible como una constante o variable temporal.
Un enlace opcional para el if declaración es la siguiente:
if let constantName = someOptional {
statements
}
Tomemos un ejemplo simple para comprender el uso del enlace opcional:
var myString:String?
myString = "Hello, Swift 4!"
if let yourString = myString {
print("Your string has - \(yourString)")
} else {
print("Your string does not have a value")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Your string has - Hello, Swift 4!
Swift 4 también presenta Tuples type, que se utilizan para agrupar varios valores en un solo valor compuesto.
Los valores de una tupla pueden ser de cualquier tipo y no es necesario que sean del mismo tipo.
Por ejemplo, ("Tutorials Point", 123) es una tupla con dos valores, uno de tipo cadena y otro de tipo entero. Es un mandato legal.
let ImplementationError = (501, "No implementado") es un error cuando algo en el servidor no está implementado. Devuelve dos valores. Código de error y descripción.
Puede crear tuplas a partir de tantos valores como desee y de cualquier número de tipos de datos diferentes.
Aquí está la sintaxis de la declaración Tuple:
var TupleName = (Value1, value2,… any number of values)
Aquí hay una declaración de Tuple:
var error501 = (501, “Not implemented”)
Puede acceder a los valores de tupla utilizando los números de índice que comienzan en 0.
Aquí hay un ejemplo de cómo acceder a valores de tupla:
print(“The code is\(error501.0)”)
print(“The definition of error is\(error501.1)”)
Puede nombrar las variables de una tupla mientras declara, y puede llamarlas usando sus nombres
var error501 = (errorCode: 501, description: “Not Implemented”)
print(error501.errorCode) // prints 501.
Las tuplas son útiles para devolver múltiples valores de una función. Por ejemplo, una aplicación web puede devolver una tupla de tipo ("String", Int) para mostrar si la carga se realizó correctamente o no.
Al devolver diferentes valores en una tupla, podemos tomar decisiones en función de los diferentes tipos de tuplas.
Note - Las tuplas son útiles para valores temporales y no son adecuadas para datos complejos.
Las constantes se refieren a valores fijos que un programa no puede alterar durante su ejecución. Las constantes pueden ser de cualquiera de los tipos de datos básicos, como una constante entera, una constante flotante, una constante de carácter o una cadena literal . También hay constantes de enumeración .
Constants se tratan como variables regulares excepto el hecho de que sus valores no se pueden modificar después de su definición.
Declaración de constantes
Antes de usar constantes, debe declararlas usando let palabra clave de la siguiente manera:
let constantName = <initial value>
A continuación se muestra un ejemplo simple para mostrar cómo declarar una constante en Swift 4:
let constA = 42
print(constA)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
42
Tipo de anotaciones
Puede proporcionar un type annotationcuando declara una constante, para tener claro el tipo de valores que la constante puede almacenar. A continuación se muestra la sintaxis:
var constantName:<data type> = <optional initial value>
El siguiente ejemplo muestra cómo declarar una constante en Swift 4 usando Anotación. Aquí es importante tener en cuenta que es obligatorio proporcionar un valor inicial mientras se crea una constante:
let constA = 42
print(constA)
let constB:Float = 3.14159
print(constB)
Cuando ejecutamos el programa anterior usando playground, obtenemos el siguiente resultado.
42
3.1415901184082
Nombrar constantes
El nombre de una constante puede estar compuesto por letras, dígitos y el carácter de subrayado. Debe comenzar con una letra o un guión bajo. Las letras mayúsculas y minúsculas son distintas porque Swift 4 es un lenguaje de programación que distingue entre mayúsculas y minúsculas.
Puede usar caracteres simples o Unicode para nombrar sus variables. Los siguientes son ejemplos válidos:
let _const = "Hello, Swift 4!"
print(_const)
let 你好 = "你好世界"
print(你好)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Hello, Swift 4!
你好世界
Constantes de impresión
Puede imprimir el valor actual de una constante o variable usando printfunción. Puede interpolar un valor de variable envolviendo el nombre entre paréntesis y escapando con una barra invertida antes del paréntesis de apertura: A continuación se muestran ejemplos válidos:
let constA = "Godzilla"
let constB = 1000.00
print("Value of \(constA) is more than \(constB) millions")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Value of Godzilla is more than 1000.0 millions
Un literal es la representación del código fuente de un valor de un entero, un número de punto flotante o un tipo de cadena. Los siguientes son ejemplos de literales:
42 // Integer literal
3.14159 // Floating-point literal
"Hello, world!" // String literal
Literales enteros
Un literal entero puede ser una constante decimal, binaria, octal o hexadecimal. Los literales binarios comienzan con 0b, los literales octales comienzan con 0o y los literales hexadecimales comienzan con 0x y nada para decimales.
Aquí hay algunos ejemplos de literales enteros:
let decimalInteger = 17 // 17 in decimal notation
let binaryInteger = 0b10001 // 17 in binary notation
let octalInteger = 0o21 // 17 in octal notation
let hexadecimalInteger = 0x11 // 17 in hexadecimal notation
Literales de coma flotante
Un literal de coma flotante tiene una parte entera, una coma decimal, una parte fraccionaria y una parte exponente. Puede representar literales de coma flotante en forma decimal o hexadecimal.
Los literales decimales de coma flotante consisten en una secuencia de dígitos decimales seguidos de una fracción decimal, un exponente decimal o ambos.
Los literales hexadecimales de coma flotante constan de un prefijo 0x, seguido de una fracción hexadecimal opcional, seguida de un exponente hexadecimal.
Aquí hay algunos ejemplos de literales de punto flotante:
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0
Literales de cadena
Un literal de cadena es una secuencia de caracteres rodeada de comillas dobles, con la siguiente forma:
"characters"
Los literales de cadena no pueden contener comillas dobles sin escape ("), una barra invertida sin escape (\), un retorno de carro o un salto de línea. Se pueden incluir caracteres especiales en los literales de cadena mediante las siguientes secuencias de escape:
Secuencia de escape | Sentido |
---|---|
\ 0 | Carácter nulo |
\\ | \personaje |
\segundo | Retroceso |
\F | Alimentación de formulario |
\norte | Nueva línea |
\ r | Retorno de carro |
\ t | Pestaña horizontal |
\ v | Pestaña vertical |
\ ' | Una frase |
\ " | Cotización doble |
\ 000 | Número octal de uno a tres dígitos |
\ xhh ... | Número hexadecimal de uno o más dígitos |
El siguiente ejemplo muestra cómo utilizar algunos literales de cadena:
let stringL = "Hello\tWorld\n\nHello\'Swift 4\'"
print(stringL)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Hello World
Hello'Swift 4'
Literales booleanos
Hay tres literales booleanos y forman parte de las palabras clave estándar de Swift 4:
Un valor de true representando verdadero.
Un valor de false representando falso.
Un valor de nil representando ningún valor.
Un operador es un símbolo que le dice al compilador que realice manipulaciones matemáticas o lógicas específicas. Objective-C es rico en operadores integrados y proporciona los siguientes tipos de operadores:
- Operadores aritméticos
- Operadores de comparación
- Operadores logicos
- Operadores bit a bit
- Operadores de Asignación
- Operadores de rango
- Operadores varios
Este tutorial explicará los operadores aritméticos, relacionales, lógicos, bit a bit, de asignación y otros, uno por uno.
Operadores aritméticos
La siguiente tabla muestra todos los operadores aritméticos compatibles con el lenguaje Swift 4. Asumir variableA tiene 10 y variable B tiene 20, entonces -
Operador | Descripción | Ejemplo |
---|---|---|
+ | Agrega dos operandos | A + B dará 30 |
- | Resta el segundo operando del primero | A - B dará -10 |
* | Multiplica ambos operandos | A * B dará 200 |
/ | Divide el numerador por el denominador | B / A dará 2 |
% | Operador de módulo y resto de después de una división entera / flotante | B% A dará 0 |
Operadores de comparación
La siguiente tabla muestra todos los operadores relacionales compatibles con el lenguaje Swift 4. Asumir variableA tiene 10 y variable B tiene 20, entonces -
Operador | Descripción | Ejemplo |
---|---|---|
== | Comprueba si los valores de dos operandos son iguales o no; si es así, entonces la condición se vuelve verdadera. | (A == B) no es cierto. |
! = | Comprueba si los valores de dos operandos son iguales o no; si los valores no son iguales, la condición se cumple. | (A! = B) es cierto. |
> | Comprueba si el valor del operando izquierdo es mayor que el valor del operando derecho; si es así, entonces la condición se vuelve verdadera. | (A> B) no es cierto. |
< | Comprueba si el valor del operando izquierdo es menor que el valor del operando derecho; si es así, entonces la condición se vuelve verdadera. | (A <B) es cierto. |
> = | Comprueba si el valor del operando izquierdo es mayor o igual que el valor del operando derecho; si es así, entonces la condición se vuelve verdadera. | (A> = B) no es cierto. |
<= | Comprueba si el valor del operando izquierdo es menor o igual que el valor del operando derecho; si es así, entonces la condición se vuelve verdadera. | (A <= B) es cierto. |
Operadores logicos
La siguiente tabla muestra todos los operadores lógicos compatibles con el lenguaje Swift 4. Asumir variableA contiene 1 y variable B tiene 0, entonces -
Operador | Descripción | Ejemplo |
---|---|---|
&& | Operador llamado lógico AND. Si ambos operandos son distintos de cero, la condición se cumple. | (A && B) es falso. |
|| | Operador OR lógico llamado. Si alguno de los dos operandos es distinto de cero, la condición se cumple. | (A || B) es cierto. |
! | Operador llamado lógico NOT. Úselo para revertir el estado lógico de su operando. Si una condición es verdadera, entonces el operador lógico NOT la convertirá en falsa. | ! (A && B) es cierto. |
Operadores bit a bit
Los operadores bit a bit trabajan en bits y realizan operaciones bit a bit. Las tablas de verdad para &, | y ^ son las siguientes:
pags | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
Assume A = 60; and B = 13;
In binary format, they will be as follows:
A = 0011 1100
B = 0000 1101
-----------------
A & B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
Los operadores bit a bit compatibles con el idioma Swift 4 se enumeran en la siguiente tabla. Asumir variableA tiene 60 y variable B tiene 13, luego 7−
Operador | Descripción | Ejemplo |
---|---|---|
Y | El operador AND binario copia un bit al resultado, si existe en ambos operandos. | (A & B) dará 12, que es 0000 1100 |
| | El operador OR binario copia un bit, si existe en cualquiera de los operandos. | (A | B) dará 61, que es 0011 1101 |
^ | El operador binario XOR copia el bit, si está establecido en un operando pero no en ambos. | (A ^ B) dará 49, que es 0011 0001 |
~ | El operador de complemento binario es unario y tiene el efecto de "voltear" bits. | (~ A) dará -61, que es 1100 0011 en forma de complemento a 2. |
<< | Operador binario de cambio a la izquierda. El valor de los operandos de la izquierda se mueve a la izquierda el número de bits especificado por el operando de la derecha. | (A << 2 dará 240, que es 1111 0000 |
>> | Operador de cambio a la derecha binario. El valor de los operandos de la izquierda se mueve hacia la derecha el número de bits especificado por el operando de la derecha. | A >> 2 dará 15, que es 0000 1111 |
Operadores de Asignación
SSwift 4 admite los siguientes operadores de asignación:
Operador | Descripción | Ejemplo |
---|---|---|
= | Operador de asignación simple, asigna valores de los operandos del lado derecho al operando del lado izquierdo | C = A + B asignará el valor de A + B en C |
+ = | Agregar operador de asignación Y, agrega el operando derecho al operando izquierdo y asigna el resultado al operando izquierdo | C + = A es equivalente a C = C + A |
- = | Restar operador de asignación AND, resta el operando derecho del operando izquierdo y asigna el resultado al operando izquierdo | C - = A es equivalente a C = C - A |
* = | Operador de asignación de multiplicar Y, multiplica el operando derecho con el operando izquierdo y asigna el resultado al operando izquierdo | C * = A es equivalente a C = C * A |
/ = | Operador de división Y asignación, divide el operando izquierdo con el operando derecho y asigna el resultado al operando izquierdo | C / = A es equivalente a C = C / A |
% = | Operador de asignación de módulo Y, toma el módulo usando dos operandos y asigna el resultado al operando izquierdo | C% = A es equivalente a C = C% A |
<< = | Operador de desplazamiento Y asignación a la izquierda | C << = 2 es lo mismo que C = C << 2 |
>> = | Operador de desplazamiento Y asignación a la derecha | C >> = 2 es lo mismo que C = C >> 2 |
& = | Operador de asignación AND bit a bit | C & = 2 es lo mismo que C = C & 2 |
^ = | Operador de asignación y OR exclusivo bit a bit | C ^ = 2 es lo mismo que C = C ^ 2 |
| = | OR inclusivo bit a bit y operador de asignación | C | = 2 es lo mismo que C = C | 2 |
Operadores de rango
Swift 4 incluye dos operadores de rango, que son atajos para expresar un rango de valores. La siguiente tabla explica estos dos operadores.
Operador | Descripción | Ejemplo |
---|---|---|
Rango cerrado | (a ... b) define un rango que va desde a hasta b, e incluye los valores ay b. | 1 ... 5 da 1, 2, 3, 4 y 5 |
Gama semiabierta | (a .. <b) define un rango que va desde a hasta b, pero no incluye b. | 1 .. <5 da 1, 2, 3 y 4 |
Rango unilateral | a…, define un rango que va desde un hasta el final de los elementos … A, define un rango desde el principio hasta un |
1 ... da 1, 2,3 ... final de elementos ... 2 da comienzo ... a 1,2 |
Operadores varios
Swift 4 admite algunos otros operadores importantes, incluidos rangey : que se explican en la siguiente tabla.
Operador | Descripción | Ejemplo |
---|---|---|
Unario menos | El signo de un valor numérico se puede alternar con un prefijo - | -3 o -4 |
Unario Plus | Devuelve el valor sobre el que opera, sin ningún cambio. | +6 da 6 |
Condicional ternario | ¿Condición? X: Y | ¿Si la condición es verdadera? Entonces valor X: De lo contrario valor Y |
Precedencia de operadores
La precedencia del operador determina la agrupación de términos en una expresión. Esto afecta cómo se evalúa una expresión. Ciertos operadores tienen mayor precedencia que otros; por ejemplo, el operador de multiplicación tiene mayor precedencia que el operador de suma.
Por ejemplo, x = 7 + 3 * 2; aquí, a x se le asigna 13, no 20 porque el operador * tiene mayor precedencia que +, por lo que primero se multiplica por 3 * 2 y luego se suma a 7.
Aquí, los operadores con mayor precedencia aparecen en la parte superior de la tabla, los que tienen la menor prioridad aparecen en la parte inferior. Dentro de una expresión, los operadores de mayor precedencia se evaluarán primero.
Operador | Descripción | Ejemplo |
---|---|---|
Operadores de expresión primaria | () []. expr ++ expr-- | de izquierda a derecha |
Operadores unarios | * & + -! ~ ++ expr --expr * /% + - >> << <> <=> = ==! = |
De derecha a izquierda |
Operadores binarios | Y ^ | && || |
de izquierda a derecha |
Operador ternario | ?: | De derecha a izquierda |
Operadores de Asignación | = + = - = * = / =% = >> = << = & = ^ = | = | De derecha a izquierda |
Coma | , | de izquierda a derecha |
Las estructuras de toma de decisiones requieren que el programador especifique una o más condiciones para ser evaluadas o probadas por el programa, junto con una declaración o declaraciones que se ejecutarán si se determina que la condición es truey, opcionalmente, otras sentencias que se ejecutarán si se determina que la condición es false.
A continuación se muestra la forma general de una estructura de toma de decisiones típica que se encuentra en la mayoría de los lenguajes de programación:
Swift 4 proporciona los siguientes tipos de declaraciones para la toma de decisiones. Haga clic en los siguientes enlaces para verificar su detalle.
No Señor | Declaración y descripción |
---|---|
1 | si declaración Una instrucción if consta de una expresión booleana seguida de una o más declaraciones. |
2 | declaración if ... else Una instrucción if puede ir seguida de una instrucción else opcional, que se ejecuta cuando la expresión booleana es falsa. |
3 | if ... else if ... else Statement Una instrucción if puede ir seguida de una instrucción else if ... else opcional, que es muy útil para probar varias condiciones utilizando una instrucción if ... else if. |
4 | declaraciones if anidadas Puede usar una instrucción if o else if dentro de otra instrucción if o else if. |
5 | declaración de cambio Una instrucción de cambio permite probar la igualdad de una variable con una lista de valores. |
Los ? : Operador
Nosotros hemos cubierto conditional operator ? : en el capítulo anterior que se puede utilizar para reemplazar if...elsedeclaraciones. Tiene la siguiente forma general:
Exp1 ? Exp2 : Exp3;
Donde Exp1, Exp2 y Exp3 son expresiones. Observe el uso y la ubicación del colon.
¿El valor de un? La expresión se determina así: Se evalúa Exp1. Si es cierto, entonces Exp2 se evalúa y se convierte en el valor de la totalidad? expresión. Si Exp1 es falso, entonces se evalúa Exp3 y su valor se convierte en el valor de la expresión.
Puede haber una situación en la que necesite ejecutar un bloque de código varias veces. En general, las sentencias se ejecutan secuencialmente: la primera sentencia de una función se ejecuta primero, seguida de la segunda, y así sucesivamente.
Los lenguajes de programación proporcionan varias estructuras de control que permiten rutas de ejecución más complicadas.
Una declaración de bucle nos permite ejecutar una declaración o grupo de declaraciones varias veces. A continuación se muestra la forma general de una declaración de bucle en la mayoría de los lenguajes de programación:
El lenguaje de programación Swift 4 proporciona los siguientes tipos de bucle para manejar los requisitos de bucle. Haga clic en los siguientes enlaces para verificar su detalle.
No Señor | Tipo de bucle y descripción |
---|---|
1 | for-in Este ciclo realiza un conjunto de declaraciones para cada elemento en un rango, secuencia, colección o progresión. |
2 | while loop Repite una declaración o un grupo de declaraciones mientras una condición determinada es verdadera. Prueba la condición antes de ejecutar el cuerpo del bucle. |
3 | repetir ... mientras bucle Como una instrucción while, excepto que prueba la condición al final del cuerpo del bucle. |
Declaraciones de control de bucle
Las sentencias de control de bucle cambian la ejecución de su secuencia normal. Cuando la ejecución abandona un ámbito, todos los objetos automáticos que se crearon en ese ámbito se destruyen.
Swift 4 admite las siguientes declaraciones de control. Haga clic en los siguientes enlaces para verificar su detalle.
No Señor | Declaración de control y descripción |
---|---|
1 | Continuar declaración Esta declaración le dice a un bucle que detenga lo que está haciendo y comience de nuevo al comienzo de la siguiente iteración a través del bucle. |
2 | declaración de ruptura Termina la instrucción de bucle y transfiere la ejecución a la instrucción que sigue inmediatamente al bucle. |
3 | declaración fallida La declaración fallthrough simula el comportamiento del cambio Swift 4 al cambio de estilo C. |
Las cadenas en Swift 4 son una colección ordenada de caracteres, como "¡Hola, mundo!" y están representados por el tipo de datos Swift 4String, que a su vez representa una colección de valores de Character tipo.
Crear una cadena
Puede crear una cadena utilizando un literal de cadena o creando una instancia de una clase de cadena de la siguiente manera:
// String creation using String literal
var stringA = "Hello, Swift 4!"
print( stringA )
// String creation using String instance
var stringB = String("Hello, Swift 4!")
print( stringB )
//Multiple line string
let stringC = """
Hey this is a
example of multiple Line
string by tutorialsPoint
"""
print(stringC)
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado
Hello, Swift 4!
Hello, Swift 4!
Hey this is a
example of multiple Line
string by tutorialsPoint
Cuerda vacía
Puede crear una cadena vacía utilizando un literal de cadena vacía o creando una instancia de la clase String como se muestra a continuación. También puede verificar si una cadena está vacía o no usando la propiedad booleanaisEmpty.
// Empty string creation using String literal
var stringA = ""
if stringA.isEmpty {
print( "stringA is empty" )
} else {
print( "stringA is not empty" )
}
// Empty string creation using String instance
let stringB = String()
if stringB.isEmpty {
print( "stringB is empty" )
} else {
print( "stringB is not empty" )
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
stringA is empty
stringB is empty
Constantes de cadena
Puede especificar si su cadena se puede modificar (o mutar) asignándola a una variable, o será constante asignándola a una constante usando let palabra clave como se muestra a continuación -
// stringA can be modified
var stringA = "Hello, Swift 4!"
stringA + = "--Readers--"
print( stringA )
// stringB can not be modified
let stringB = String("Hello, Swift 4!")
stringB + = "--Readers--"
print( stringB )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Playground execution failed: error: <EXPR>:10:1: error: 'String' is not
convertible to '@lvalue UInt8'
stringB + = "--Readers--"
Interpolación de cadenas
La interpolación de cadenas es una forma de construir un nuevo valor de cadena a partir de una combinación de constantes, variables, literales y expresiones al incluir sus valores dentro de una cadena literal.
Cada elemento (variable o constante) que inserta en el literal de cadena está envuelto en un par de paréntesis, precedido por una barra invertida. Aquí hay un ejemplo simple:
var varA = 20
let constA = 100
var varC:Float = 20.0
var stringA = "\(varA) times \(constA) is equal to \(varC * 100)"
print( stringA )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
20 times 100 is equal to 2000.0
Concatenación de cadenas
Puede utilizar el operador + para concatenar dos cadenas o una cadena y un carácter, o dos caracteres. Aquí hay un ejemplo simple:
let constA = "Hello,"
let constB = "World!"
var stringA = constA + constB
print( stringA )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Hello,World!
Longitud de la cuerda
Swift 4 cuerdas no tienen lengthpropiedad, pero puede usar la función global count () para contar el número de caracteres en una cadena. Aquí hay un ejemplo simple:
var varA = "Hello, Swift 4!"
print( "\(varA), length is \((varA.count))" )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Hello, Swift 4!, length is 15
Comparación de cadenas
Puede utilizar el operador == para comparar dos cadenas de variables o constantes. Aquí hay un ejemplo simple:
var varA = "Hello, Swift 4!"
var varB = "Hello, World!"
if varA == varB {
print( "\(varA) and \(varB) are equal" )
} else {
print( "\(varA) and \(varB) are not equal" )
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Hello, Swift 4! and Hello, World! are not equal
Iterando cadena
Las cadenas son nuevamente una colección de valores en swift 4, por lo que podemos iterar sobre cadenas usando bucles. -
for chars in "ThisString" {
print(chars, terminator: " ")
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
T h i s S t r i n g
Cadenas Unicode
Puede acceder a una representación UTF-8 y UTF-16 de una cadena iterando sobre sus propiedades utf8 y utf16 como se demuestra en el siguiente ejemplo:
var unicodeString = "Dog???"
print("UTF-8 Codes: ")
for code in unicodeString.utf8 {
print("\(code) ")
}
print("\n")
print("UTF-16 Codes: ")
for code in unicodeString.utf16 {
print("\(code) ")
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
UTF-8 Codes:
68
111
103
63
63
63
UTF-16 Codes:
68
111
103
63
63
63
Funciones y operadores de cadenas
Swift 4 admite una amplia gama de métodos y operadores relacionados con Strings:
No Señor | Funciones / Operadores y propósito |
---|---|
1 | isEmpty Un valor booleano que determina si una cadena está vacía o no. |
2 | hasPrefix(prefix: String) Función para comprobar si una determinada cadena de parámetros existe como prefijo de la cadena o no. |
3 | hasSuffix(suffix: String) Función para comprobar si una determinada cadena de parámetros existe como sufijo de la cadena o no. |
4 | toInt() Función para convertir un valor de cadena numérico en entero. |
5 | count() Función global para contar el número de caracteres en una cadena. |
6 | utf8 Propiedad para devolver una representación UTF-8 de una cadena. |
7 | utf16 Propiedad para devolver una representación UTF-16 de una cadena. |
8 | unicodeScalars Propiedad para devolver una representación escalar Unicode de una cadena. |
9 | + Operador para concatenar dos cadenas, o una cadena y un carácter, o dos caracteres. |
10 | += Operador para agregar una cadena o carácter a una cadena existente. |
11 | == Operador para determinar la igualdad de dos cadenas. |
12 | < Operador para realizar una comparación lexicográfica para determinar si una cadena se evalúa como menor que otra. |
13 | startIndex Para obtener el valor en el índice inicial de la cadena. |
14 | endIndex Para obtener el valor en el índice final de la cadena. |
15 | Indices Para acceder a los índices uno a uno. es decir, todos los caracteres de la cadena uno por uno. |
dieciséis | insert("Value", at: position) Para insertar un valor en una posición. |
17 | remove(at: position) removeSubrange(range) para eliminar un valor en una posición o para eliminar un rango de valores de la cadena. |
18 | reversed() devuelve el reverso de una cadena |
UN character en Swift es un literal de cadena de un solo carácter, dirigido por el tipo de datos Character. Eche un vistazo al siguiente ejemplo. Utiliza dos constantes de caracteres:
let char1: Character = "A"
let char2: Character = "B"
print("Value of char1 \(char1)")
print("Value of char2 \(char2)")
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Value of char1 A
Value of char2 B
Si intenta almacenar más de un carácter en una variable o constante de tipo carácter, Swift 4 no lo permitirá. Intente escribir el siguiente ejemplo en Swift 4 Playground y obtendrá un error incluso antes de la compilación.
// Following is wrong in Swift 4
let char: Character = "AB"
print("Value of char \(char)")
Variables de caracteres vacías
No es posible crear una constante o variable de carácter vacía que tendrá un valor vacío. La siguiente sintaxis no es posible:
// Following is wrong in Swift 4
let char1: Character = ""
var char2: Character = ""
print("Value of char1 \(char1)")
print("Value of char2 \(char2)")
Accediendo a caracteres desde cadenas
Como se explicó al analizar las cadenas de Swift 4, String representa una colección de valores de caracteres en un orden específico. Entonces podemos acceder a caracteres individuales de la Cadena dada iterando sobre esa cadena con unfor-in bucle -
for ch in "Hello" {
print(ch)
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
H
e
l
l
o
Concatenación de cadenas con caracteres
El siguiente ejemplo demuestra cómo se puede concatenar el personaje de Swift 4 con String de Swift 4.
var varA:String = "Hello "
let varB:Character = "G"
varA.append( varB )
print("Value of varC = \(varA)")
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Value of varC = Hello G
Las matrices Swift 4 se utilizan para almacenar listas ordenadas de valores del mismo tipo. Swift 4 pone un control estricto que no le permite ingresar un tipo incorrecto en una matriz, incluso por error.
Si asigna una matriz creada a una variable, siempre será mutable, lo que significa que puede cambiarla agregando, eliminando o cambiando sus elementos; pero si asigna una matriz a una constante, esa matriz es inmutable y su tamaño y contenido no se pueden cambiar.
Crear matrices
Puede crear una matriz vacía de un cierto tipo utilizando la siguiente sintaxis de inicializador:
var someArray = [SomeType]()
Aquí está la sintaxis para crear una matriz de un tamaño dado a * e inicializarla con un valor:
var someArray = [SomeType](count: NumbeOfElements, repeatedValue: InitialValue)
Puede utilizar la siguiente declaración para crear una matriz vacía de Int tipo que tiene 3 elementos y el valor inicial como cero -
var someInts = [Int](count: 3, repeatedValue: 0)
A continuación se muestra un ejemplo más para crear una matriz de tres elementos y asignar tres valores a esa matriz:
var someInts:[Int] = [10, 20, 30]
Acceso a matrices
Puede recuperar un valor de una matriz utilizando subscript sintaxis, pasando el índice del valor que desea recuperar entre corchetes inmediatamente después del nombre de la matriz de la siguiente manera:
var someVar = someArray[index]
Aquí el indexcomienza desde 0, lo que significa que se puede acceder al primer elemento usando el índice como 0, se puede acceder al segundo elemento usando el índice como 1 y así sucesivamente. El siguiente ejemplo muestra cómo crear, inicializar y acceder a matrices:
var someInts = [Int](count: 3, repeatedValue: 10)
var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Value of first element is 10
Value of second element is 10
Value of third element is 10
Modificar matrices
Puedes usar append()método u operador de asignación de adición (+ =) para agregar un nuevo elemento al final de una matriz. Eche un vistazo al siguiente ejemplo. Aquí, inicialmente, creamos una matriz vacía y luego agregamos nuevos elementos a la misma matriz:
var someInts = [Int]()
someInts.append(20)
someInts.append(30)
someInts += [40]
var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Value of first element is 20
Value of second element is 30
Value of third element is 40
Puede modificar un elemento existente de una matriz asignando un nuevo valor a un índice determinado como se muestra en el siguiente ejemplo:
var someInts = [Int]()
someInts.append(20)
someInts.append(30)
someInts += [40]
// Modify last element
someInts[2] = 50
var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Value of first element is 20
Value of second element is 30
Value of third element is 50
Iterando sobre una matriz
Puedes usar for-in bucle para iterar sobre todo el conjunto de valores en una matriz como se muestra en el siguiente ejemplo:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for item in someStrs {
print(item)
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Apple
Amazon
Google
Puedes usar enumerate() función que devuelve el índice de un elemento junto con su valor como se muestra a continuación en el siguiente ejemplo:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for (index, item) in someStrs.enumerated() {
print("Value at index = \(index) is \(item)")
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google
Agregar dos matrices
Puede usar el operador de suma (+) para agregar dos matrices del mismo tipo que producirán una nueva matriz con una combinación de valores de las dos matrices de la siguiente manera:
var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = intsA + intsB
for item in intsC {
print(item)
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
2
2
1
1
1
La propiedad del recuento
Puede utilizar el modo de solo lectura count propiedad de una matriz para averiguar el número de elementos en una matriz que se muestra a continuación:
var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = intsA + intsB
print("Total items in intsA = \(intsA.count)")
print("Total items in intsB = \(intsB.count)")
print("Total items in intsC = \(intsC.count)")
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Total items in intsA = 2
Total items in intsB = 3
Total items in intsC = 5
La propiedad vacía
Puede utilizar el modo de solo lectura empty propiedad de una matriz para averiguar si una matriz está vacía o no, como se muestra a continuación:
var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = [Int]()
print("intsA.isEmpty = \(intsA.isEmpty)")
print("intsB.isEmpty = \(intsB.isEmpty)")
print("intsC.isEmpty = \(intsC.isEmpty)")
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
intsA.isEmpty = false
intsB.isEmpty = false
intsC.isEmpty = true
Rápido 4 sets se utilizan para almacenar valores distintos de los mismos tipos pero no tienen un orden definido como lo tienen las matrices.
Puede usar conjuntos en lugar de matrices si el orden de los elementos no es un problema o si desea asegurarse de que no haya valores duplicados. (los conjuntos permiten solo valores distintos).
Un tipo debe ser hash para ser almacenado en un conjunto. Un valor hash es un valor Int que es igual para objetos iguales. Por ejemplo, si x == y, entoncesx.hashvalue == y.hashvalue.
Todos los valores rápidos básicos son de tipo hash de forma predeterminada y se pueden usar como valores establecidos.
Creando Conjuntos
Puede crear un conjunto vacío de un cierto tipo utilizando la siguiente sintaxis de inicializador:
var someSet = Set<Character>() //Character can be replaced by data type of set.
Acceder y modificar conjuntos
Puede acceder o modificar un conjunto utilizando sus métodos y propiedades:
El método "count" se puede utilizar para mostrar el número de elementos del conjunto.
someSet.count // prints the number of elements
El método "insertar" se puede utilizar para insertar valores en el conjunto.
someSet.insert("c") // adds the element to Set.
De manera similar, isEmpty se puede usar para verificar si el conjunto está vacío.
someSet.isEmpty // returns true or false depending on the set Elements.
El método "eliminar" se puede utilizar para eliminar el valor del conjunto.
someSet.remove("c") // removes a element , removeAll() can be used to remove all elements
El método "contiene" se puede utilizar para comprobar la existencia de valor en un conjunto.
someSet.contains("c") // to check if set contains this value.
Iterando sobre un conjunto
Puede iterar sobre un conjunto usando el bucle for-in -
for items in someSet {
print(someSet)
}
//Swift sets are not in an ordered way, to iterate over a set in ordered way use
for items in someSet.sorted() {
print(someSet)
}
Realización de operaciones de set
Puede realizar operaciones básicas de conjuntos en conjuntos rápidos.
A continuación se muestran los métodos para realizar operaciones de conjuntos:
- Intersection
- Union
- subtracting
let evens: Set = [10,12,14,16,18]
let odds: Set = [5,7,9,11,13]
let primes = [2,3,5,7]
odds.union(evens).sorted()
// [5,7,9,10,11,12,13,14,16,18]
odds.intersection(evens).sorted()
//[]
odds.subtracting(primes).sorted()
//[9, 11, 13]
Rápido 4 dictionariesse utilizan para almacenar listas desordenadas de valores del mismo tipo. Swift 4 realiza un control estricto que no le permite ingresar un tipo incorrecto en un diccionario, incluso por error.
Los diccionarios Swift 4 utilizan un identificador único conocido como keypara almacenar un valor que luego se puede referenciar y buscar a través de la misma clave. A diferencia de los elementos de una matriz, los elementos de unadictionaryno tiene un pedido específico. Puedes usar undictionary cuando necesite buscar valores basados en sus identificadores.
Una clave de diccionario puede ser un número entero o una cadena sin restricción, pero debe ser única dentro de un diccionario.
Si asigna un diccionario creado a una variable, siempre será mutable, lo que significa que puede cambiarlo agregando, quitando o cambiando sus elementos. Pero si asigna un diccionario a una constante, ese diccionario es inmutable y su tamaño y contenido no se pueden cambiar.
Crear diccionario
Puede crear un diccionario vacío de un determinado tipo utilizando la siguiente sintaxis de inicializador:
var someDict = [KeyType: ValueType]()
Puede utilizar la siguiente sintaxis simple para crear un diccionario vacío cuya clave será de tipo Int y los valores asociados serán cadenas:
var someDict = [Int: String]()
Aquí hay un ejemplo para crear un diccionario a partir de un conjunto de valores dados:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
Inicialización basada en secuencia
Swift 4 le permite crear diccionarios a partir de matrices (pares clave-valor).
var cities = [“Delhi”,”Bangalore”,”Hyderabad”]
Puede utilizar la siguiente sintaxis simple para crear un diccionario vacío cuya clave será de tipo Int y los valores asociados serán cadenas:
var Distance = [2000,10, 620]
Aquí hay un ejemplo para crear un diccionario a partir de un conjunto de valores dados:
let cityDistanceDict = Dictionary(uniqueKeysWithValues: zip(cities, Distance))
Las líneas de código anteriores crearán un diccionario con Ciudades como clave y Distancia como Valor -
Filtración
Swift 4 le permite filtrar valores de un diccionario.
var closeCities = cityDistanceDict.filter { $0.value < 1000 }
Si ejecutamos el código anterior, nuestro diccionario closeCities será.
["Bangalore" : 10 , "Hyderabad" : 620]
Agrupación de diccionario
Swift 4 le permite crear agrupaciones de valores de diccionario.
var cities = ["Delhi","Bangalore","Hyderabad","Dehradun","Bihar"]
Puede utilizar la siguiente sintaxis simple para agrupar los valores del diccionario según el primer alfabeto.
var GroupedCities = Dictionary(grouping: cities ) { $0.first! }
El resultado del código anterior será
["D" :["Delhi","Dehradun"], "B" : ["Bengaluru","Bihar"], "H" : ["Hyderabad"]]
Acceder a diccionarios
Puede recuperar un valor de un diccionario utilizando la sintaxis de subíndice, pasando la clave del valor que desea recuperar entre corchetes inmediatamente después del nombre del diccionario de la siguiente manera:
var someVar = someDict[key]
Veamos el siguiente ejemplo para crear, inicializar y acceder a valores desde un diccionario:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someVar = someDict[1]
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Value of key = 1 is Optional("One")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")
Modificar diccionarios
Puedes usar updateValue(forKey:)método para agregar un valor existente a una clave dada del diccionario. Este método devuelve un valor opcional del tipo de valor del diccionario. Aquí hay un ejemplo simple:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict.updateValue("New value of one", forKey: 1)
var someVar = someDict[1]
print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")
Puede modificar un elemento existente de un diccionario asignando un nuevo valor a una clave determinada, como se muestra en el siguiente ejemplo:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict[1]
someDict[1] = "New value of one"
var someVar = someDict[1]
print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")
Eliminar pares clave-valor
Puedes usar removeValueForKey()método para eliminar un par clave-valor de un diccionario. Este método elimina el par clave-valor si existe y devuelve el valor eliminado, o devuelve nil si no existía ningún valor. Aquí hay un ejemplo simple:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var removedValue = someDict.removeValue(forKey: 2)
print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")
También puede utilizar la sintaxis de subíndice para eliminar un par clave-valor de un diccionario asignando un valor de nilpara esa llave. Aquí hay un ejemplo simple:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
someDict[2] = nil
print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")
Iterando sobre un diccionario
Puedes usar un for-in bucle para iterar sobre todo el conjunto de pares clave-valor en un diccionario, como se muestra en el siguiente ejemplo:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (index, keyValue) in someDict.enumerated() {
print("Dictionary key \(index) - Dictionary value \(keyValue)")
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Dictionary key 2 - Dictionary value Two
Dictionary key 3 - Dictionary value Three
Dictionary key 1 - Dictionary value One
Puedes usar enumerate() función que devuelve el índice del elemento junto con su par (clave, valor) como se muestra a continuación en el ejemplo:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, value) in someDict.enumerated() {
print("Dictionary key \(key) - Dictionary value \(value)")
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Dictionary key 0 - Dictionary value (key: 2, value: "Two")
Dictionary key 1 - Dictionary value (key: 3, value: "Three")
Dictionary key 2 - Dictionary value (key: 1, value: "One")
Convertir a matrices
Puede extraer una lista de pares clave-valor de un diccionario determinado para crear matrices separadas para claves y valores. Aquí hay un ejemplo:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
let dictKeys = [Int](someDict.keys)
let dictValues = [String](someDict.values)
print("Print Dictionary Keys")
for (key) in dictKeys {
print("\(key)")
}
print("Print Dictionary Values")
for (value) in dictValues {
print("\(value)")
}
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Print Dictionary Keys
2
3
1
Print Dictionary Values
Two
Three
One
La propiedad del recuento
Puede utilizar el modo de solo lectura count propiedad de un diccionario para averiguar el número de elementos en un diccionario como se muestra a continuación:
var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]
print("Total items in someDict1 = \(someDict1.count)")
print("Total items in someDict2 = \(someDict2.count)")
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
Total items in someDict1 = 3
Total items in someDict2 = 2
La propiedad vacía
Puedes usar solo lectura empty propiedad de un diccionario para averiguar si un diccionario está vacío o no, como se muestra a continuación:
var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]
var someDict3:[Int:String] = [Int:String]()
print("someDict1 = \(someDict1.isEmpty)")
print("someDict2 = \(someDict2.isEmpty)")
print("someDict3 = \(someDict3.isEmpty)")
Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:
someDict1 = false
someDict2 = false
someDict3 = true
Una función es un conjunto de declaraciones organizadas juntas para realizar una tarea específica. Una función Swift 4 puede ser tan simple como una función C simple o tan compleja como una función del lenguaje Objective C. Nos permite pasar valores de parámetros locales y globales dentro de las llamadas a funciones.
Function Declaration - le dice al compilador sobre el nombre de una función, el tipo de retorno y los parámetros.
Function Definition - Proporciona el cuerpo real de la función.
Las funciones de Swift 4 contienen el tipo de parámetro y sus tipos de retorno.
Definición de función
En Swift 4, una función se define mediante la palabra clave "func". Cuando una función se define recientemente, puede tomar uno o varios valores como 'parámetros' de entrada para la función y procesará las funciones en el cuerpo principal y devolverá los valores a las funciones como 'tipos de retorno' de salida.
Cada función tiene un nombre de función, que describe la tarea que realiza la función. Para usar una función, "llama" a esa función con su nombre y pasa valores de entrada (conocidos como argumentos) que coinciden con los tipos de parámetros de la función. Los parámetros de función también se denominan "tuplas".
Los argumentos de una función siempre deben proporcionarse en el mismo orden que la lista de parámetros de la función y los valores de retorno van seguidos de →.
Sintaxis
func funcname(Parameters) -> returntype {
Statement1
Statement2
---
Statement N
return parameters
}
Eche un vistazo al siguiente código. El nombre del estudiante se declara como un tipo de datos de cadena declarado dentro de la función 'estudiante' y cuando se llama a la función, devolverá el nombre del estudiante.
func student(name: String) -> String {
return name
}
print(student(name: "First Program"))
print(student(name: "About Functions"))
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
First Program
About Functions
Llamar a una función
Supongamos que definimos una función llamada 'pantalla' para considerar, por ejemplo, para mostrar los números, una función con el nombre de función 'pantalla' se inicializa primero con el argumento 'no1' que contiene el tipo de datos enteros. Luego, el argumento 'no1' se asigna al argumento 'a' que, en adelante, apuntará al mismo tipo de datos entero. Ahora el argumento 'a' se devuelve a la función. Aquí la función display () mantendrá el valor entero y devolverá los valores enteros cada vez que se invoca la función.
func display(no1: Int) -> Int {
let a = no1
return a
}
print(display(no1: 100))
print(display(no1: 200))
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
100
200
Parámetros y valores devueltos
Swift 4 proporciona parámetros de función flexibles y sus valores de retorno de valores simples a complejos. Al igual que en C y Objective C, las funciones en Swift 4 también pueden tomar varias formas.
Funciones con parámetros
Se accede a una función pasando los valores de sus parámetros al cuerpo de la función. Podemos pasar valores de parámetros individuales a múltiples como tuplas dentro de la función.
func mult(no1: Int, no2: Int) -> Int {
return no1*no2
}
print(mult(no1: 2, no2: 20))
print(mult(no1: 3, no2: 15))
print(mult(no1: 4, no2: 30))
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
40
45
120
Funciones sin parámetros
También podemos tener funciones sin ningún parámetro.
Sintaxis
func funcname() -> datatype {
return datatype
}
A continuación se muestra un ejemplo que tiene una función sin un parámetro:
func votersname() -> String {
return "Alice"
}
print(votersname())
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Alice
Funciones con valores devueltos
Las funciones también se utilizan para devolver valores de tipo de datos de cadena, enteros y flotantes como tipos de retorno. Para encontrar el número más grande y más pequeño en una matriz dada, la función 'ls' se declara con tipos de datos enteros grandes y pequeños.
Una matriz se inicializa para contener valores enteros. Luego, la matriz se procesa y todos y cada uno de los valores de la matriz se leen y comparan con su valor anterior. Cuando el valor es menor que el anterior, se almacena en el argumento 'pequeño', de lo contrario, se almacena en el argumento 'grande' y los valores se devuelven llamando a la función.
func ls(array: [Int]) -> (large: Int, small: Int) {
var lar = array[0]
var sma = array[0]
for i in array[1..<array.count] {
if i < sma {
sma = i
} else if i > lar {
lar = i
}
}
return (lar, sma)
}
let num = ls(array: [40,12,-5,78,98])
print("Largest number is: \(num.large) and smallest number is: \(num.small)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Largest number is: 98 and smallest number is: -5
Funciones sin valores de retorno
Algunas funciones pueden tener argumentos declarados dentro de la función sin ningún valor de retorno. El siguiente programa declaraa y bcomo argumentos de la función sum (). dentro de la función misma los valores de los argumentosa y b se pasan invocando la función sum () y sus valores se imprimen eliminando así los valores de retorno.
func sum(a: Int, b: Int) {
let a = a + b
let b = a - b
print(a, b)
}
sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
30 20
50 40
30 24
Funciones con tipos de devolución opcionales
Swift 4 presenta una función 'opcional' para eliminar los problemas mediante la introducción de una medida de seguridad. Considere, por ejemplo, que estamos declarando el tipo de retorno de valores de función como entero, pero qué sucederá cuando la función devuelva un valor de cadena o un valor nulo. En ese caso, el compilador devolverá un valor de error. Se introducen 'opcionales' para eliminar estos problemas.
Las funciones opcionales tomarán dos formas, 'valor' y 'nulo'. Mencionaremos 'Opcionales' con el carácter de clave reservada '?' para comprobar si la tupla devuelve un valor o un valor nulo.
func minMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty { return nil }
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
min is -6 and max is 109
Los '' opcionales '' se utilizan para verificar valores 'nulos' o basura, lo que consume mucho tiempo en la depuración y hace que el código sea eficiente y legible para el usuario.
Funciones Nombres de parámetros locales versus externos
Nombres de parámetros locales
Se accede a los nombres de los parámetros locales solo dentro de la función.
func sample(number: Int) {
print(number)
}
Aquí el funcEl número de argumento de muestra se declara como variable interna, ya que la función sample () accede a él internamente. Aquí el 'número' se declara como variable local, pero la referencia a la variable se hace fuera de la función con la siguiente declaración:
func sample(number: Int) {
print(number)
}
sample(number: 1)
sample(number: 2)
sample(number: 3)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
1
2
3
Nombres de parámetros externos
Los nombres de parámetros externos nos permiten nombrar parámetros de una función para que su propósito sea más claro. Por ejemplo, a continuación, puede nombrar dos parámetros de función y luego llamar a esa función de la siguiente manera:
func pow(firstArg a: Int, secondArg b: Int) -> Int {
var res = a
for _ in 1..<b {
res = res * a
}
print(res)
return res
}
pow(firstArg:5, secondArg:3)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
125
Parámetros Variadic
Cuando queremos definir una función con varios argumentos, podemos declarar los miembros como parámetros 'variadic'. Los parámetros se pueden especificar como variables mediante (···) después del nombre del parámetro.
func vari<N>(members: N...){
for i in members {
print(i)
}
}
vari(members: 4,3,5)
vari(members: 4.5, 3.1, 5.6)
vari(members: "Swift 4", "Enumerations", "Closures")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
4
3
5
4.5
3.1
5.6
Swift 4
Enumerations
Closures
Parámetros constantes, variables y de E / S
Las funciones por defecto consideran los parámetros como 'constantes', mientras que el usuario puede declarar los argumentos de las funciones también como variables. Ya discutimos que la palabra clave 'let' se usa para declarar parámetros constantes y los parámetros variables se definen con la palabra clave 'var'.
Los parámetros de E / S en Swift 4 brindan funcionalidad para retener los valores de los parámetros aunque sus valores se modifiquen después de la llamada a la función. Al comienzo de la definición del parámetro de función, se declara la palabra clave 'inout' para retener los valores de los miembros.
Deriva la palabra clave 'inout' ya que sus valores se pasan 'in' a la función y el cuerpo de la función accede y modifica sus valores y se devuelve 'out' de la función para modificar el argumento original.
Las variables solo se pasan como un argumento para el parámetro in-out, ya que solo sus valores se modifican dentro y fuera de la función. Por lo tanto, no es necesario declarar cadenas y literales como parámetros de entrada y salida. '&' antes de un nombre de variable se refiere a que estamos pasando el argumento al parámetro in-out.
func temp(a1: inout Int, b1: inout Int) {
let t = a1
a1 = b1
b1 = t
}
var no = 2
var co = 10
temp(a1: &no, b1: &co)
print("Swapped values are \(no), \(co)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Swapped values are 10, 2
Tipos de funciones y su uso
Todas y cada una de las funciones siguen la función específica al considerar los parámetros de entrada y generan el resultado deseado.
func inputs(no1: Int, no2: Int) -> Int {
return no1/no2
}
A continuación se muestra un ejemplo:
func inputs(no1: Int, no2: Int) -> Int {
return no1/no2
}
print(inputs(no1: 20, no2: 10))
print(inputs(no1: 36, no2: 6))
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
2
6
Aquí la función se inicializa con dos argumentos no1 y no2 como tipos de datos enteros y su tipo de retorno también se declara como 'int'
Func inputstr(name: String) -> String {
return name
}
Aquí la función se declara como string tipo de datos.
Las funciones también pueden tener void los tipos de datos y esas funciones no devolverán nada.
func inputstr() {
print("Swift 4 Functions")
print("Types and its Usage")
}
inputstr()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Swift 4 Functions
Types and its Usage
La función anterior se declara como una función nula sin argumentos ni valores de retorno.
Uso de tipos de funciones
Las funciones se pasan primero con argumentos de tipo entero, flotante o de cadena y luego se pasan como constantes o variables a la función como se menciona a continuación.
var addition: (Int, Int) -> Int = sum
Aquí sum es un nombre de función que tiene variables enteras 'a' y 'b' que ahora se declara como una variable para la adición del nombre de la función. De ahora en adelante, tanto la función de suma como la función de suma tienen el mismo número de argumentos declarados como tipo de datos entero y también devuelven valores enteros como referencias.
func sum(a: Int, b: Int) -> Int {
return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Result: 129
Tipos de funciones como tipos de parámetros y tipos de retorno
También podemos pasar la función en sí como tipos de parámetros a otra función.
func sum(a: Int, b: Int) -> Int {
return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")
func another(addition: (Int, Int) -> Int, a: Int, b: Int) {
print("Result: \(addition(a, b))")
}
another(sum, 10, 20)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Result: 129
Result: 30
Funciones anidadas
Una función anidada proporciona la posibilidad de llamar a la función externa invocando la función interna.
func calcDecrement(forDecrement total: Int) -> () -> Int {
var overallDecrement = 0
func decrementer() -> Int {
overallDecrement -= total
return overallDecrement
}
return decrementer
}
let decrem = calcDecrement(forDecrement: 30)
print(decrem())
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
-30
Los cierres en Swift 4 son similares a los de las funciones autónomas organizadas como bloques y llamadas en cualquier lugar como los lenguajes C y Objective C. Las constantes y referencias de variables definidas dentro de las funciones se capturan y almacenan en cierres. Las funciones se consideran casos especiales de cierres y adoptan las tres formas siguientes:
Funciones globales | Funciones anidadas | Expresiones de cierre |
---|---|---|
Ten un nombre. No capture ningún valor | Ten un nombre. Capturar valores de la función adjunta | Los cierres sin nombre capturan valores de los bloques adyacentes |
Las expresiones de cierre en el lenguaje Swift 4 siguen estilos de sintaxis nítidos, optimizados y ligeros que incluyen.
- Inferir tipos de parámetros y valores de retorno del contexto.
- Rendimientos implícitos de cierres de expresión única.
- Nombres de argumentos taquigráficos y
- Sintaxis de cierre final
Sintaxis
A continuación se muestra una sintaxis genérica para definir el cierre que acepta parámetros y devuelve un tipo de datos:
{
(parameters) −> return type in
statements
}
A continuación se muestra un ejemplo simple:
let studname = { print("Welcome to Swift Closures") }
studname()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Welcome to Swift Closures
El siguiente cierre acepta dos parámetros y devuelve un valor bool:
{
(Int, Int) −> Bool in
Statement1
Statement 2
---
Statement n
}
A continuación se muestra un ejemplo simple:
let divide = {
(val1: Int, val2: Int) -> Int in
return val1 / val2
}
let result = divide(200, 20)
print (result)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
10
Expresiones en cierres
Las funciones anidadas proporcionan una forma conveniente de nombrar y definir bloques de código. En lugar de representar la declaración de función completa y las construcciones de nombre se utilizan para denotar funciones más cortas. La representación de la función en una declaración breve clara con sintaxis enfocada se logra a través de expresiones de cierre.
Programa de orden ascendente
La clasificación de una cadena se logra mediante la función reservada de teclas Swift 4s "sorted" que ya está disponible en la biblioteca estándar. La función ordenará las cadenas dadas en orden ascendente y devolverá los elementos en una nueva matriz con el mismo tamaño y tipo de datos mencionados en la matriz anterior. La matriz anterior sigue siendo la misma.
Dos argumentos están representados dentro de la función ordenada:
Valores de tipo conocido representados como matrices.
El contenido de la matriz (Int, Int) y devuelve un valor booleano (Bool) si la matriz está ordenada correctamente, devolverá un valor verdadero, de lo contrario, devolverá falso.
Una función normal con una cadena de entrada se escribe y se pasa a la función ordenada para ordenar las cadenas en la nueva matriz que se muestra a continuación:
func ascend(s1: String, s2: String) -> Bool {
return s1 > s2
}
let stringcmp = ascend(s1: "Swift 4", s2: "great")
print (stringcmp)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
true
La matriz inicial que se clasificará para el helado se indica como "Swift 4" y "excelente". La función para ordenar la matriz se declara como tipo de datos de cadena y su tipo de retorno se menciona como booleano. Ambas cadenas se comparan y clasifican en orden ascendente y se almacenan en una nueva matriz. Si la clasificación se realiza correctamente, la función devolverá un valor verdadero; de lo contrario, devolverá falso.
La sintaxis de la expresión de cierre utiliza:
- parámetros constantes,
- parámetros variables, y
- parámetros inout.
La expresión de cierre no admitía valores predeterminados. Los parámetros variables y las tuplas también se pueden utilizar como tipos de parámetros y tipos de retorno.
let sum = {
(no1: Int, no2: Int) -> Int in
return no1 + no2
}
let digits = sum(10, 20)
print(digits)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
30
Los parámetros y declaraciones de tipo de retorno que se mencionan en la declaración de la función también se pueden representar mediante la función de expresión de cierre en línea con la palabra clave 'in'. Una vez que se declaran los tipos de parámetro y retorno, la palabra clave 'in' se usa para indicar que el cuerpo del cierre.
Rendimientos implícitos de una sola expresión
Aquí, el tipo de función del segundo argumento de la función ordenada deja claro que el cierre debe devolver un valor Bool. Debido a que el cuerpo del cierre contiene una sola expresión (s1> s2) que devuelve un valor bool, no hay ambigüedad y la palabra clave return se puede omitir.
Para devolver una declaración de expresión única en cierres de expresión, se omite la palabra clave 'return' en su parte de declaración.
var count:[Int] = [5, 10, -6, 75, 20]
let descending = count.sorted(by: { n1, n2 in n1 > n2 })
let ascending = count.sorted(by: { n1, n2 in n1 < n2 })
print(descending)
print(ascending)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]
La declaración en sí define claramente que cuando la cadena1 es mayor que la cadena 2, devuelve verdadero; de lo contrario, es falsa, por lo que se omite aquí la declaración de devolución.
Cierres de tipo conocido
Considere la suma de dos números. Sabemos que la suma devolverá el tipo de datos entero. Por lo tanto, los cierres de tipo conocido se declaran como:
let sub = {
(no1: Int, no2: Int) -> Int in
return no1 - no2
}
let digits = sub(10, 20)
print(digits)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
-10
Declaración de nombres de argumentos taquigráficos como cierres
Swift 4 proporciona automáticamente nombres abreviados de argumentos a los cierres en línea, que se pueden usar para hacer referencia a los valores de los argumentos del cierre con los nombres $ 0, $1, $2 y así sucesivamente.
var shorthand: (String, String) -> String
shorthand = { $1 }
print(shorthand("100", "200"))
Aquí, $ 0 y $ 1 se refieren al primer y segundo argumento String del cierre.
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
200
Swift 4 facilita al usuario representar cierres en línea como nombres abreviados de argumentos al representar $ 0, $1, $2 --- $ n.
La lista de argumentos de cierres se omite en la sección de definición cuando representamos nombres abreviados de argumentos dentro de expresiones de cierre. Según el tipo de función, se derivarán los nombres abreviados de los argumentos. Dado que el argumento abreviado se define en el cuerpo de la expresión, se omite la palabra clave 'in'.
Cierres como funciones del operador
Swift 4 proporciona una manera fácil de acceder a los miembros simplemente proporcionando funciones de operador como cierres. En los ejemplos anteriores, la palabra clave 'Bool' se usa para devolver 'verdadero' cuando las cadenas son iguales; de lo contrario, devuelve 'falso'.
La expresión se hace aún más simple por la función del operador en el cierre como -
let numb = [98, -20, -30, 42, 18, 35]
var sortedNumbers = numb.sorted ({
(left: Int, right: Int) -> Bool in
return left < right
})
let asc = numb.sorted(<)
print(asc)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
[-30, -20, 18, 35, 42, 98]
Cierres como remolques
Pasar el argumento final de la función a una expresión de cierre se declara con la ayuda de 'Trailing Closures'. Está escrito fuera de la función () con {}. Su uso es necesario cuando no es posible escribir la función en línea en una sola línea.
reversed = sorted(names) { $0 > $1}
donde {$ 0> $ 1} se representan como cierres finales declarados fuera de (nombres).
import Foundation
var letters = ["North", "East", "West", "South"]
let twoletters = letters.map({
(state: String) -> String in
return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString
})
let stletters = letters.map() {
$0.substringToIndex(advance($0.startIndex, 2)).uppercaseString
}
print(stletters)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
[NO, EA, WE, SO]
Captura de valores y tipos de referencia
En Swift 4, la captura de constantes y valores de variables se realiza con la ayuda de cierres. Además, hace referencia y modifica los valores de esas constantes y variables dentro del cuerpo de cierre, aunque las variables ya no existan.
La captura de valores constantes y variables se logra mediante el uso de una función anidada escribiendo la función con en el cuerpo de otra función.
Una función anidada captura:
- Argumentos de funciones externas.
- Capture constantes y variables definidas dentro de la función Outer.
En Swift 4, cuando se declara una constante o variable dentro de una función, el cierre también crea automáticamente una referencia a esas variables. También proporciona la posibilidad de hacer referencia a más de dos variables como el mismo cierre de la siguiente manera:
let decrem = calcDecrement(forDecrement: 18)
decrem()
aquí oneDecrement y las variables de Decremento señalarán el mismo bloque de memoria como referencia de cierre.
func calcDecrement(forDecrement total: Int) -> () -> Int {
var overallDecrement = 100
func decrementer() -> Int {
overallDecrement -= total
print(overallDecrement)
return overallDecrement
}
return decrementer
}
let decrem = calcDecrement(forDecrement: 18)
decrem()
decrem()
decrem()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
82
64
46
Cuando todas y cada una de las veces que se llama a la función externa calcDecrement, invoca la función decrementer () y disminuye el valor en 18 y devuelve el resultado con la ayuda de la función externa calcDecrement. Aquí calcDecrement actúa como un cierre.
Aunque la función decrementer () no tiene ningún argumento, el cierre por defecto se refiere a las variables 'globalDecrement' y 'total' capturando sus valores existentes. La copia de los valores de las variables especificadas se almacena con la función new decrementer (). Swift 4 maneja las funciones de administración de memoria asignando y desasignando espacios de memoria cuando las variables no están en uso.
Una enumeración es un tipo de datos definido por el usuario que consta de un conjunto de valores relacionados. Palabra claveenum se utiliza para definir el tipo de datos enumerados.
Funcionalidad de enumeración
La enumeración en Swift 4 también se parece a la estructura de C y Objective C.
Se declara en una clase y se accede a sus valores a través de la instancia de esa clase.
El valor del miembro inicial se define mediante inicializadores de enumeración.
Su funcionalidad también se amplía al garantizar la funcionalidad del protocolo estándar.
Sintaxis
Las enumeraciones se introducen con la palabra clave enum y colocan su definición completa dentro de un par de llaves:
enum enumname {
// enumeration values are described here
}
Por ejemplo, puede definir una enumeración para los días de la semana de la siguiente manera:
enum DaysofaWeek {
case Sunday
case Monday
---
case Saturday
}
Ejemplo
enum names {
case Swift
case Closures
}
var lang = names.Closures
lang = .Closures
switch lang {
case .Swift:
print("Welcome to Swift")
case .Closures:
print("Welcome to Closures")
default:
print("Introduction")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Welcome to Closures
La enumeración Swift 4 no asigna a sus miembros un valor predeterminado como C y Objetivo C. En cambio, los miembros se definen explícitamente por sus nombres de enumeración. El nombre de la enumeración debe comenzar con una letra mayúscula (por ejemplo, enum DaysofaWeek).
var weekDay = DaysofaWeek.Sunday
Aquí, el nombre de enumeración 'DaysofaWeek' se asigna a una variable weekday.Sunday. Le informa al compilador que el tipo de datos que pertenece a Sunday se asignará a los miembros de enumeración posteriores de esa clase en particular. Una vez que se define el tipo de datos del miembro enum, se puede acceder a los miembros pasando valores y cálculos adicionales.
Enumeración con instrucción Switch
La declaración Swift 4 'Switch' también sigue a la selección de múltiples vías. Solo se accede a una variable en un momento determinado en función de la condición especificada. El caso predeterminado en la instrucción switch se usa para atrapar casos no especificados.
enum Climate {
case India
case America
case Africa
case Australia
}
var season = Climate.America
season = .America
switch season {
case .India:
print("Climate is Hot")
case .America:
print("Climate is Cold")
case .Africa:
print("Climate is Moderate")
case .Australia:
print("Climate is Rainy")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Climate is Cold
El programa primero define Clima como el nombre de la enumeración. Entonces sus miembros como 'India', 'América', 'África' y 'Australia' son declarados pertenecientes a la clase 'Clima'. Ahora el miembro América está asignado a una variable de temporada. Además, Switch case verá los valores correspondientes a .America y se ramificará a esa declaración en particular. La salida se mostrará como "El clima es frío". Asimismo, se puede acceder a todos los miembros mediante declaraciones de cambio. Cuando no se cumple la condición, se imprime de forma predeterminada "El clima no es predecible".
La enumeración se puede clasificar adicionalmente en valores asociados y valores brutos.
Diferencia entre valores asociados y valores brutos
Valores asociados | Valores crudos |
Diferentes tipos de datos | Mismos tipos de datos |
Ejemplo: enumeración {10,0.8, "Hola"} | Ej: enum {10,35,50} |
Los valores se crean en base a constante o variable | Valores rellenados previamente |
Varía cuando se declara cada vez | El valor para el miembro es el mismo |
Enumeración con valores asociados
enum Student {
case Name(String)
case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
print("Student name is: \(studName).")
case .Mark(let Mark1, let Mark2, let Mark3):
print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Student Marks are: 98,97,95.
Considere, por ejemplo, acceder al nombre de los estudiantes y las marcas aseguradas en tres asignaturas. El nombre de enumeración se declara como estudiante y los miembros presentes en la clase de enumeración son nombres que pertenecen al tipo de datos de cadena, las marcas se representan como mark1, mark2 y mark3 del tipo de datos Integer. Para acceder al nombre del estudiante o las notas que ha obtenido
var studDetails = Student.Name("Swift")
var studMarks = Student.Mark(98,97,95)
Ahora, el caso del interruptor imprimirá el nombre del estudiante si se ejecuta ese bloque de caso, de lo contrario, imprimirá las marcas obtenidas por el estudiante. Si ambas condiciones fallan, se ejecutará el bloque predeterminado.
Enumeración con valores brutos
Los valores brutos pueden ser cadenas, caracteres o cualquiera de los tipos de números enteros o de punto flotante. Cada valor bruto debe ser único dentro de su declaración de enumeración. Cuando se utilizan números enteros para valores brutos, se incrementan automáticamente si no se especifica ningún valor para algunos de los miembros de la enumeración.
enum Month: Int {
case January = 1, February, March, April, May, June, July, August,
September, October, November, December
}
let yearMonth = Month.May.rawValue
print("Value of the Month is: \(yearMonth).")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Value of the Month is: 5.
Swift 4 proporciona un bloque de construcción flexible para hacer uso de constructos como estructuras. Haciendo uso de estas estructuras una vez se pueden definir métodos y propiedades de construcciones.
A diferencia de C y Objective C
La estructura no necesita requerir archivos de implementación e interfaz.
La estructura nos permite crear un solo archivo y extender su interfaz automáticamente a otros bloques.
En Estructura, los valores de las variables se copian y pasan en códigos posteriores devolviendo una copia de los valores antiguos para que los valores no se puedan alterar.
Sintaxis
Structures are defined with a 'Struct' Keyword.
struct nameStruct {
Definition 1
Definition 2
---
Definition N
}
Definición de una estructura
Por ejemplo, supongamos que tenemos que acceder al registro de los estudiantes que contiene las calificaciones de tres materias y averiguar el total de tres materias. Aquí markStruct se utiliza para inicializar una estructura con tres marcas como tipo de datos 'Int'.
struct MarkStruct {
var mark1: Int
var mark2: Int
var mark3: Int
}
Acceder a la estructura y sus propiedades
Se accede a los miembros de la estructura por su nombre de estructura. Las instancias de la estructura se inicializan con la palabra clave 'let'.
struct studentMarks {
var mark1 = 100
var mark2 = 200
var mark3 = 300
}
let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Mark1 is 100
Mark2 is 200
Mark3 is 300
Se accede a las marcas de los estudiantes mediante el nombre de estructura 'StudentMarks'. Los miembros de la estructura se inicializan como mark1, mark2, mark3 con valores de tipo entero. Luego, la estructura studentMarks () se pasa a las 'marcas' con la palabra clave 'dejar'. De ahora en adelante, las 'marcas' contendrán los valores de los miembros de la estructura. Ahora, los valores se imprimen accediendo a los valores de los miembros de la estructura mediante '.' con sus nombres inicializados.
struct MarksStruct {
var mark: Int
init(mark: Int) {
self.mark = mark
}
}
var aStruct = MarksStruct(mark: 98)
var bStruct = aStruct // aStruct and bStruct are two structs with the same value!
bStruct.mark = 97
print(aStruct.mark) // 98
print(bStruct.mark) // 97
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
98
97
Mejores prácticas de uso de estructuras
El lenguaje Swift 4 proporciona la funcionalidad para definir estructuras como tipos de datos personalizados para construir los bloques de funciones. Las instancias de estructura se pasan por su valor a los bloques definidos para su posterior manipulación.
Necesidad de tener estructuras
Encapsular valores de datos simples.
Copiar los datos encapsulados y sus propiedades asociadas por 'valores' en lugar de por 'referencias'.
Estructura para 'Copiar' y 'Referencia'.
Las estructuras en Swift 4 transmiten a sus miembros sus valores en lugar de sus referencias.
struct markStruct {
var mark1: Int
var mark2: Int
var mark3: Int
init(mark1: Int, mark2: Int, mark3: Int) {
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
var marks = markStruct(mark1: 98, mark2: 96, mark3:100)
print(marks.mark1)
print(marks.mark2)
print(marks.mark3)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
98
96
100
Otro ejemplo
struct markStruct {
var mark1: Int
var mark2: Int
var mark3: Int
init(mark1: Int, mark2: Int, mark3: Int) {
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
var fail = markStruct(mark1: 34, mark2: 42, mark3: 13)
print(fail.mark1)
print(fail.mark2)
print(fail.mark3)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
34
42
13
La estructura 'markStruct' se define primero con sus miembros mark1, mark2 y mark3. Ahora las variables de las clases miembro se inicializan para contener valores enteros. Luego, la copia de los miembros de la estructura se crea con la palabra clave "self". Una vez que se crea la copia de los miembros de la estructura, el bloque de estructura con sus marcas de parámetro se pasa a la variable 'marcas' que ahora contendrá las marcas de los estudiantes. Luego, las marcas se imprimen como 98, 96, 100. En el siguiente paso para los mismos miembros de estructura, se usa otra instancia denominada "falla" para señalar los mismos miembros de estructura con diferentes marcas. Entonces, los resultados ahora se imprimen como 34, 42, 13. Esto explica claramente que las estructuras tendrán una copia de las variables miembro y luego pasarán los miembros a sus próximos bloques de funciones.
Las clases en Swift 4 son bloques de construcción de construcciones flexibles. De manera similar a las constantes, variables y funciones, el usuario puede definir propiedades y métodos de clase. Swift 4 nos proporciona la funcionalidad de que, al declarar clases, los usuarios no necesitan crear interfaces o archivos de implementación. Swift 4 nos permite crear clases como un solo archivo y las interfaces externas se crearán por defecto una vez que se inicialicen las clases.
Beneficios de tener clases
La herencia adquiere las propiedades de una clase a otra clase
La conversión de tipos permite al usuario verificar el tipo de clase en tiempo de ejecución
Los desinicializadores se encargan de liberar recursos de memoria
El recuento de referencias permite que la instancia de clase tenga más de una referencia
Características comunes de clases y estructuras
- Las propiedades se definen para almacenar valores
- Los subíndices se definen para proporcionar acceso a los valores.
- Los métodos se inicializan para mejorar la funcionalidad
- Los inicializadores definen el estado inicial
- La funcionalidad se expande más allá de los valores predeterminados
- Confirmación de los estándares de funcionalidad del protocolo
Sintaxis
Class classname {
Definition 1
Definition 2
---
Definition N
}
Definición de clase
class student {
var studname: String
var mark: Int
var mark2: Int
}
La sintaxis para crear instancias
let studrecord = student()
Ejemplo
class MarksStruct {
var mark: Int
init(mark: Int) {
self.mark = mark
}
}
class studentMarks {
var mark = 300
}
let marks = studentMarks()
print("Mark is \(marks.mark)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Mark is 300
Acceder a las propiedades de clase como tipos de referencia
Se puede acceder a las propiedades de la clase mediante el '.' sintaxis. El nombre de la propiedad está separado por un '.' después del nombre de la instancia.
class MarksStruct {
var mark: Int
init(mark: Int) {
self.mark = mark
}
}
class studentMarks {
var mark1 = 300
var mark2 = 400
var mark3 = 900
}
let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Mark1 is 300
Mark2 is 400
Mark3 is 900
Operadores de identidad de clase
Las clases en Swift 4 se refieren a múltiples constantes y variables que apuntan a una sola instancia. Para conocer las constantes y variables que apuntan a una instancia de clase particular, se utilizan operadores de identidad. Las instancias de clase siempre se pasan por referencia. En las clases, las instancias NSString, NSArray y NSDictionary siempre se asignan y se transmiten como una referencia a una instancia existente, en lugar de como una copia.
Idéntico a los operadores | No idéntico a los operadores |
---|---|
El operador utilizado es (===) | El operador utilizado es (! ==) |
Devuelve verdadero cuando dos constantes o variables apuntan a una misma instancia | Devuelve verdadero cuando dos constantes o variables apuntan a una instancia diferente |
class SampleClass: Equatable {
let myProperty: String
init(s: String) {
myProperty = s
}
}
func ==(lhs: SampleClass, rhs: SampleClass) -> Bool {
return lhs.myProperty == rhs.myProperty
}
let spClass1 = SampleClass(s: "Hello")
let spClass2 = SampleClass(s: "Hello")
spClass1 === spClass2 // false
print("\(spClass1)")
spClass1 !== spClass2 // true
print("\(spClass2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
main.SampleClass
main.SampleClass
El lenguaje Swift 4 proporciona propiedades de clase, enumeración o estructura para asociar valores. Las propiedades se pueden clasificar en propiedades almacenadas y propiedades calculadas.
Diferencia entre propiedades almacenadas y propiedades calculadas
Propiedad almacenada | Propiedad calculada |
---|---|
Almacene valores constantes y variables como instancia | Calcule un valor en lugar de almacenar el valor |
Proporcionado por clases y estructuras | Proporcionado por clases, enumeraciones y estructuras |
Tanto las propiedades almacenadas como las calculadas están asociadas con el tipo de instancia. Cuando las propiedades están asociadas con sus valores de tipo, se define como 'Propiedades de tipo'. Las propiedades almacenadas y calculadas generalmente se asocian con instancias de un tipo particular. Sin embargo, las propiedades también se pueden asociar con el tipo en sí. Estas propiedades se conocen como propiedades de tipo. También se utilizan observadores de propiedades
- Para observar el valor de las propiedades almacenadas
- Para observar la propiedad de la subclase heredada derivada de la superclase
Propiedades almacenadas
Swift 4 introduce el concepto de propiedad almacenada para almacenar las instancias de constantes y variables. Las propiedades almacenadas de las constantes se definen con la palabra clave 'let' y las propiedades almacenadas de las variables se definen con la palabra clave 'var'.
- Durante la definición, la propiedad almacenada proporciona un 'valor predeterminado'
- Durante la inicialización, el usuario puede inicializar y modificar los valores iniciales.
struct Number {
var digits: Int
let pi = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.pi)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
67
3.1415
Considere la siguiente línea en el código anterior:
let pi = 3.1415
Aquí, la variable pi se inicializa como un valor de propiedad almacenado con la instancia pi = 3.1415. Por lo tanto, siempre que se haga referencia a la instancia, solo tendrá el valor 3.1415.
Otro método para tener una propiedad almacenada es tener estructuras constantes. Entonces, toda la instancia de las estructuras se considerará como 'Propiedades almacenadas de constantes'.
struct Number {
var digits: Int
let numbers = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
error: cannot assign to 'numbers' in 'n'
n.numbers = 8.7
En lugar de reinicializar el 'número' a 8.7, devolverá un mensaje de error que indica que el 'número' se declara como constante.
Propiedad almacenada perezosa
Swift 4 proporciona una propiedad flexible llamada 'Propiedad almacenada diferida' donde no calculará los valores iniciales cuando la variable se inicialice por primera vez. El modificador 'lazy' se usa antes de la declaración de variable para tenerlo como una propiedad almacenada lazy.
Se utilizan propiedades perezosas -
- Para retrasar la creación de objetos.
- Cuando la propiedad depende de otras partes de una clase, que aún no se conocen
class sample {
lazy var no = number() // `var` declaration is required.
}
class number {
var name = "Swift 4"
}
var firstsample = sample()
print(firstsample.no.name)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Swift 4
Variables de instancia
En Objective C, las propiedades almacenadas también tienen variables de instancia con fines de respaldo para almacenar los valores declarados en la propiedad almacenada.
Swift 4 integra ambos conceptos en una sola declaración de 'propiedad almacenada'. En lugar de tener una variable de instancia correspondiente y un valor de respaldo, la 'propiedad almacenada' contiene toda la información integrada definida en una sola ubicación sobre la propiedad de las variables por nombre de variable, tipo de datos y funcionalidades de administración de memoria.
Propiedades calculadas
En lugar de almacenar los valores, las propiedades calculadas proporcionan un captador y un definidor opcional para recuperar y establecer otras propiedades y valores indirectamente.
class sample {
var no1 = 0.0, no2 = 0.0
var length = 300.0, breadth = 150.0
var middle: (Double, Double) {
get {
return (length / 2, breadth / 2)
}
set(axis){
no1 = axis.0 - (length / 2)
no2 = axis.1 - (breadth / 2)
}
}
}
var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)
print(result.no1)
print(result.no2)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
(150.0, 75.0)
-150.0
-65.0
Cuando una propiedad calculada deja el nuevo valor como indefinido, el valor predeterminado se establecerá para esa variable en particular.
Propiedades calculadas como propiedades de solo lectura
Una propiedad de solo lectura en una propiedad calculada se define como una propiedad con getter pero sin setter. Siempre se usa para devolver un valor. Además, se accede a las variables a través de un '.' Sintaxis pero no se puede establecer en otro valor.
class film {
var head = ""
var duration = 0.0
var metaInfo: [String:String] {
return [
"head": self.head,
"duration":"\(self.duration)"
]
}
}
var movie = film()
movie.head = "Swift 4 Properties"
movie.duration = 3.09
print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Swift 4 Properties
3.09
Propiedades calculadas como observadores de propiedades
En Swift 4 para observar y responder a los valores de las propiedades, se utilizan Observadores de propiedades. Todas y cada una de las veces que se establecen valores de propiedad, se llama a los observadores de propiedades. Excepto las propiedades almacenadas diferidas, podemos agregar observadores de propiedades a la propiedad 'heredada' mediante el método 'invalidación'.
Los observadores de propiedades pueden definirse por
Antes de almacenar el valor - willset
Después de almacenar el nuevo valor - didset
Cuando se establece una propiedad en un inicializador willset y no se pueden llamar observadores didset.
class Samplepgm {
var counter: Int = 0 {
willSet(newTotal){
print("Total Counter is: \(newTotal)")
}
didSet {
if counter > oldValue {
print("Newly Added Counter \(counter - oldValue)")
}
}
}
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
Variables locales y globales
Las variables locales y globales se declaran para calcular y observar las propiedades.
Variables locales | Variables globales |
---|---|
Variables que se definen dentro de una función, método o contexto de cierre. | Variables que se definen fuera del contexto de función, método, cierre o tipo. |
Se utiliza para almacenar y recuperar valores. | Se utiliza para almacenar y recuperar valores. |
Las propiedades almacenadas se utilizan para obtener y establecer los valores. | Las propiedades almacenadas se utilizan para obtener y establecer los valores. |
También se utilizan propiedades calculadas. | También se utilizan propiedades calculadas. |
Propiedades de tipo
Las propiedades se definen en la sección Definición de tipo con llaves {} y el alcance de las variables también se definió previamente. Para definir propiedades de tipo para tipos de valor, se usa la palabra clave 'estática' y para los tipos de clase se usa la palabra clave 'clase'.
Sintaxis
struct Structname {
static var storedTypeProperty = " "
static var computedTypeProperty: Int {
// return an Int value here
}
}
enum Enumname {
static var storedTypeProperty = " "
static var computedTypeProperty: Int {
// return an Int value here
}
}
class Classname {
class var computedTypeProperty: Int {
// return an Int value here
}
}
Consultar y configurar propiedades
Al igual que las propiedades de instancia, las propiedades de tipo se consultan y se establecen con '.' Sintaxis solo en el tipo en lugar de apuntar a la instancia.
struct StudMarks {
static let markCount = 97
static var totalCount = 0
var InternalMarks: Int = 0 {
didSet {
if InternalMarks > StudMarks.markCount {
InternalMarks = StudMarks.markCount
}
if InternalMarks > StudMarks.totalCount {
StudMarks.totalCount = InternalMarks
}
}
}
}
var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()
stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks)
stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
97
87
En el lenguaje Swift 4, las funciones asociadas con tipos particulares se denominan métodos. En Objective C, las Clases se utilizan para definir métodos, mientras que el lenguaje Swift 4 proporciona al usuario flexibilidad para tener métodos para Clases, Estructuras y Enumeraciones.
Métodos de instancia
En el lenguaje Swift 4, se accede a las instancias de Clases, Estructuras y Enumeración a través de los métodos de instancia.
Los métodos de instancia proporcionan funcionalidad
- Para acceder y modificar las propiedades de la instancia
- funcionalidad relacionada con la necesidad de la instancia
El método de instancia se puede escribir dentro de las llaves {}. Tiene acceso implícito a métodos y propiedades de la instancia de tipo. Cuando se llama a una instancia específica del tipo, obtendrá acceso a esa instancia en particular.
Sintaxis
func funcname(Parameters) -> returntype {
Statement1
Statement2
---
Statement N
return parameters
}
Ejemplo
class calculations {
let a: Int
let b: Int
let res: Int
init(a: Int, b: Int) {
self.a = a
self.b = b
res = a + b
}
func tot(c: Int) -> Int {
return res - c
}
func result() {
print("Result is: \(tot(c: 20))")
print("Result is: \(tot(c: 50))")
}
}
let pri = calculations(a: 600, b: 300)
pri.result()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Result is: 880
Result is: 850
Cálculos de clase define dos métodos de instancia:
- init () está definido para sumar dos números ayb y almacenarlo en el resultado 'res'
- tot () se usa para restar la 'res' de pasar el valor 'c'
Finalmente, para imprimir los métodos de cálculo con valores para ay b se llama. Se accede a los métodos de instancia con '.' sintaxis de puntos
Nombres de parámetros locales y externos
Las funciones Swift 4 describen declaraciones tanto locales como globales para sus variables. De manera similar, las convenciones de nomenclatura de Swift 4 Methods también se parecen a las de Objective C. Pero las características de las declaraciones de nombres de parámetros locales y globales son diferentes para funciones y métodos. El primer parámetro en Swift 4 se conoce por nombres de preposición como 'con', 'para' y 'por' para acceder fácilmente a las convenciones de nomenclatura.
Swift 4 proporciona flexibilidad en los métodos al declarar el nombre del primer parámetro como nombres de parámetros locales y los nombres de parámetros restantes como nombres de parámetros globales. Aquí los métodos Swift 4 declaran 'no1' como nombres de parámetros locales. 'no2' se utiliza para declaraciones globales y se accede a él a través del programa.
class division {
var count: Int = 0
func incrementBy(no1: Int, no2: Int) {
count = no1 / no2
print(count)
}
}
let counter = division()
counter.incrementBy(no1: 1800, no2: 3)
counter.incrementBy(no1: 1600, no2: 5)
counter.incrementBy(no1: 11000, no2: 3)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
600
320
3666
Nombre del parámetro externo con el símbolo # y _
Aunque los métodos de Swift 4 proporcionan los nombres de los primeros parámetros para las declaraciones locales, el usuario tiene la posibilidad de modificar los nombres de los parámetros de declaraciones locales a globales. Esto se puede hacer anteponiendo el símbolo '#' al nombre del primer parámetro. Al hacerlo, se puede acceder al primer parámetro de forma global en todos los módulos.
Cuando el usuario necesita acceder a los nombres de los parámetros posteriores con un nombre externo, el nombre de los métodos se anula con la ayuda del símbolo '_'.
class multiplication {
var count: Int = 0
func incrementBy(no1: Int, no2: Int) {
count = no1 * no2
print(count)
}
}
let counter = multiplication()
counter.incrementBy(no1: 800, no2: 3)
counter.incrementBy(no1: 100, no2: 5)
counter.incrementBy(no1: 15000, no2: 3)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
2400
500
45000
Propiedad propia en métodos
Los métodos tienen una propiedad implícita conocida como 'self' para todas sus instancias de tipo definidas. La propiedad 'Self' se utiliza para hacer referencia a las instancias actuales para sus métodos definidos.
class calculations {
let a: Int
let b: Int
let res: Int
init(a: Int, b: Int) {
self.a = a
self.b = b
res = a + b
print("Inside Self Block: \(res)")
}
func tot(c: Int) -> Int {
return res - c
}
func result() {
print("Result is: \(tot(c: 20))")
print("Result is: \(tot(c: 50))")
}
}
let pri = calculations(a: 600, b: 300)
let sum = calculations(a: 1200, b: 300)
pri.result()
sum.result()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Inside Self Block: 900
Inside Self Block: 1500
Result is: 880
Result is: 850
Result is: 1480
Result is: 1450
Modificación de tipos de valor a partir de métodos de instancia
En Swift 4, las estructuras del lenguaje y las enumeraciones pertenecen a tipos de valores que no pueden ser alterados por sus métodos de instancia. Sin embargo, el lenguaje Swift 4 proporciona flexibilidad para modificar los tipos de valores mediante el comportamiento 'mutante'. Mutate realizará cualquier cambio en los métodos de instancia y volverá a la forma original después de la ejecución del método. Además, por la propiedad 'self' se crea una nueva instancia para su función implícita y reemplazará el método existente después de su ejecución
struct area {
var length = 1
var breadth = 1
func area() -> Int {
return length * breadth
}
mutating func scaleBy(res: Int) {
length *= res
breadth *= res
print(length)
print(breadth)
}
}
var val = area(length: 3, breadth: 5)
val.scaleBy(res: 3)
val.scaleBy(res: 30)
val.scaleBy(res: 300)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
9
15
270
450
81000
135000
Propiedad propia para el método de mutación
Los métodos de mutación combinados con la propiedad 'self' asignan una nueva instancia al método definido.
struct area {
var length = 1
var breadth = 1
func area() -> Int {
return length * breadth
}
mutating func scaleBy(res: Int) {
self.length *= res
self.breadth *= res
print(length)
print(breadth)
}
}
var val = area(length: 3, breadth: 5)
val.scaleBy(res: 13)
Cuando ejecutamos el programa anterior usando playground, obtenemos el siguiente resultado. -
39
65
Métodos de tipo
Cuando se llama a una instancia particular de un método, se llama como método de instancia; y cuando el método llama a un tipo particular de método, se llama como 'Métodos de tipo'. Los métodos de tipo para 'clases' se definen con la palabra clave 'func' y los métodos de tipo de estructuras y enumeraciones se definen con la palabra clave 'estática' antes de la palabra clave 'func'.
Los métodos de tipo son llamados y accesibles por '.' sintaxis donde en lugar de llamar a una instancia en particular se invoca todo el método.
class Math {
class func abs(number: Int) -> Int {
if number < 0 {
return (-number)
} else {
return number
}
}
}
struct absno {
static func abs(number: Int) -> Int {
if number < 0 {
return (-number)
} else {
return number
}
}
}
let no = Math.abs(number: -35)
let num = absno.abs(number: -5)
print(no)
print(num)
Cuando ejecutamos el programa anterior usando playground, obtenemos el siguiente resultado. -
35
5
El acceso a los elementos miembros de una colección, secuencia y lista en Clases, Estructuras y Enumeraciones se realiza con la ayuda de subíndices. Estos subíndices se utilizan para almacenar y recuperar los valores con la ayuda de index. Se accede a los elementos de matriz con la ayuda de someArray [índice] y se puede acceder a sus elementos miembros subsiguientes en una instancia de Dictionary como someDicitonary [clave].
Para un solo tipo, los subíndices pueden variar de declaraciones simples a múltiples. Podemos usar el subíndice apropiado para sobrecargar el tipo de valor de índice pasado al subíndice. Los subíndices también varían de una dimensión a una dimensión múltiple según los requisitos de los usuarios para sus declaraciones de tipo de datos de entrada.
Sintaxis de declaración de subíndice y su uso
Repasemos las propiedades calculadas. Los subíndices también siguen la misma sintaxis que la de las propiedades calculadas. Para consultar instancias de tipo, los subíndices se escriben dentro de un corchete seguido del nombre de la instancia. La sintaxis del subíndice sigue la misma estructura sintáctica que la del 'método de instancia' y la sintaxis de 'propiedad calculada'. La palabra clave 'subíndice' se utiliza para definir subíndices y el usuario puede especificar uno o varios parámetros con sus tipos de retorno. Los subíndices pueden tener propiedades de lectura-escritura o de solo lectura y las instancias se almacenan y recuperan con la ayuda de las propiedades 'getter' y 'setter' como las propiedades calculadas.
Sintaxis
subscript(index: Int) −> Int {
get {
// used for subscript value declarations
}
set(newValue) {
// definitions are written here
}
}
Ejemplo 1
struct subexample {
let decrementer: Int
subscript(index: Int) -> Int {
return decrementer / index
}
}
let division = subexample(decrementer: 100)
print("The number is divisible by \(division[9]) times")
print("The number is divisible by \(division[2]) times")
print("The number is divisible by \(division[3]) times")
print("The number is divisible by \(division[5]) times")
print("The number is divisible by \(division[7]) times")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
The number is divisible by 11 times
The number is divisible by 50 times
The number is divisible by 33 times
The number is divisible by 20 times
The number is divisible by 14 times
Ejemplo 2
class daysofaweek {
private var days = ["Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "saturday"]
subscript(index: Int) -> String {
get {
return days[index]
}
set(newValue) {
self.days[index] = newValue
}
}
}
var p = daysofaweek()
print(p[0])
print(p[1])
print(p[2])
print(p[3])
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Sunday
Monday
Tuesday
Wednesday
Opciones en subíndice
Los subíndices toman de uno a varios parámetros de entrada y estos parámetros de entrada también pertenecen a cualquier tipo de datos. También pueden utilizar parámetros variables y variadic. Los subíndices no pueden proporcionar valores de parámetros predeterminados ni utilizar parámetros de entrada y salida.
La definición de varios subíndices se denomina "sobrecarga de subíndices", donde una clase o estructura puede proporcionar múltiples definiciones de subíndices según sea necesario. Estos múltiples subíndices se infieren en función de los tipos de valores que se declaran entre las llaves del subíndice.
struct Matrix {
let rows: Int, columns: Int
var print: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
print = Array(count: rows * columns, repeatedValue: 0.0)
}
subscript(row: Int, column: Int) -> Double {
get {
return print[(row * columns) + column]
}
set {
print[(row * columns) + column] = newValue
}
}
}
var mat = Matrix(rows: 3, columns: 3)
mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0
print("\(mat[0,0])")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
1.0
El subíndice Swift 4 admite declaraciones de un solo parámetro a múltiples parámetros para los tipos de datos apropiados. El programa declara la estructura 'Matrix' como una matriz de matriz de 2 * 2 dimensiones para almacenar tipos de datos 'Double'. El parámetro Matrix se ingresa con tipos de datos Integer para declarar filas y columnas.
Se crea una nueva instancia de Matrix pasando el recuento de filas y columnas a la inicialización como se muestra a continuación.
var mat = Matrix(rows: 3, columns: 3)
Los valores de la matriz se pueden definir pasando valores de fila y columna al subíndice, separados por una coma, como se muestra a continuación.
mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0
La capacidad de tomar más forma se define como herencia. Generalmente, una clase puede heredar métodos, propiedades y funcionalidades de otra clase. Las clases se pueden categorizar aún más en subclase y superclase.
Sub Class - cuando una clase hereda propiedades, métodos y funciones de otra clase, se llama subclase
Super Class - La clase que contiene propiedades, métodos y funciones para heredar otras clases de sí misma se llama como una superclase
Las clases de Swift 4 contienen una superclase que llama y accede a métodos, propiedades, funciones y métodos primarios. Además, los observadores de propiedades también se utilizan para agregar una propiedad y modificar los métodos de propiedad almacenados o calculados.
Clase base
Una clase que no hereda métodos, propiedades o funciones de otra clase se denomina 'Clase base'.
class StudDetails {
var stname: String!
var mark1: Int!
var mark2: Int!
var mark3: Int!
init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
self.stname = stname
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
let stname = "Swift 4"
let mark1 = 98
let mark2 = 89
let mark3 = 76
print(stname)
print(mark1)
print(mark2)
print(mark3)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Swift 4
98
89
76
La clase con nombre de clase StudDetails se define aquí como una clase base que se utiliza para contener el nombre de los estudiantes, y tres asignaturas marcan como mark1, mark2 y mark3. La palabra clave 'let' se usa para inicializar el valor de la clase base y el valor de la clase base se muestra en el patio de recreo con la ayuda de la función 'imprimir'.
Subclase
El acto de basar una nueva clase en una clase existente se define como 'Subclase'. La subclase hereda las propiedades, métodos y funciones de su clase base. Para definir una subclase ':' se usa antes del nombre de la clase base
class StudDetails {
var mark1: Int;
var mark2: Int;
init(stm1:Int, results stm2:Int) {
mark1 = stm1;
mark2 = stm2;
}
func print() {
print("Mark1:\(mark1), Mark2:\(mark2)")
}
}
class display : StudDetails {
init() {
super.init(stm1: 93, results: 89)
}
}
let marksobtained = display()
marksobtained.print()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Mark1:93, Mark2:89
La clase 'StudDetails' se define como una superclase donde se declaran las calificaciones de los estudiantes y la subclase 'display' se usa para heredar las calificaciones de su superclase. La subclase define las calificaciones de los estudiantes y llama al método print () para mostrar las calificaciones de los estudiantes.
Primordial
Acceder a la subclase de instancia de superclase, métodos de tipo, instancia, propiedades de tipo y subíndices proporciona el concepto de anulación. La palabra clave 'override' se usa para invalidar los métodos declarados en la superclase.
Acceso a métodos, propiedades y subíndices de superclase
La palabra clave 'super' se utiliza como prefijo para acceder a los métodos, propiedades y subíndices declarados en la superclase
Primordial | Acceso a métodos, propiedades y subíndices |
Métodos | super.somemethod () |
Propiedades | super.someProperty () |
Subíndices | super [someIndex] |
Anulación de métodos
Los métodos heredados de instancia y tipo pueden ser reemplazados por la palabra clave 'override' a nuestros métodos definidos en nuestra subclase. Aquí print () se anula en la subclase para acceder a la propiedad type mencionada en la superclase print (). También se crea una nueva instancia de la superclase cricket () como 'cricinstance'.
class cricket {
func print() {
print("Welcome to Swift 4 Super Class")
}
}
class tennis: cricket {
override func print() {
print("Welcome to Swift 4 Sub Class")
}
}
let cricinstance = cricket()
cricinstance.print()
let tennisinstance = tennis()
tennisinstance.print()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Welcome to Swift Super Class
Welcome to Swift Sub Class
Anulación de propiedad
Puede anular una propiedad de clase o instancia heredada para proporcionar su propio captador y definidor personalizado para esa propiedad, o para agregar observadores de propiedad para permitir que la propiedad primordial observe cuándo cambia el valor de la propiedad subyacente.
Anulación de captadores y definidores de propiedades
Swift 4 permite al usuario proporcionar un captador y definidor personalizado para anular la propiedad heredada, ya sea una propiedad almacenada o calculada. La subclase no conoce el nombre y el tipo de propiedad heredada. Por lo tanto, es esencial que el usuario especifique en la subclase, el nombre y el tipo de la propiedad principal especificada en la superclase.
Esto se puede hacer de dos formas:
Cuando se define setter para anular la propiedad, el usuario también tiene que definir getter.
Cuando no queremos modificar el getter de propiedad heredada, simplemente podemos pasar el valor heredado por la sintaxis 'super.someProperty' a la superclase.
class Circle {
var radius = 12.5
var area: String {
return "of rectangle for \(radius) "
}
}
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " is now overridden as \(print)"
}
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Radius of rectangle for 25.0 is now overridden as 3
Observadores de propiedades primordiales
Cuando es necesario agregar una nueva propiedad para una propiedad heredada, se introduce el concepto de "anulación de propiedad" en Swift 4. Esto notifica al usuario cuando se modifica el valor de la propiedad heredada. Pero la invalidación no es aplicable para propiedades almacenadas constantes heredadas y propiedades computadas heredadas de solo lectura.
class Circle {
var radius = 12.5
var area: String {
return "of rectangle for \(radius) "
}
}
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " is now overridden as \(print)"
}
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
class Square: Rectangle {
override var radius: Double {
didSet {
print = Int(radius/5.0)+1
}
}
}
let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Radius of rectangle for 25.0 is now overridden as 3
Radius of rectangle for 100.0 is now overridden as 21
Propiedad final para evitar la anulación
Cuando el usuario no necesita que otros accedan a métodos, propiedades o subíndices de superclase, Swift 4 introduce la propiedad 'final' para evitar la anulación. Una vez que se declara la propiedad 'final', los subíndices no permitirán que se anulen los métodos, propiedades y subíndices de la superclase. No existe ninguna disposición para tener una propiedad 'final' en 'superclase'. Cuando se declara la propiedad 'final', el usuario está restringido a crear más subclases.
final class Circle {
final var radius = 12.5
var area: String {
return "of rectangle for \(radius) "
}
}
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " is now overridden as \(print)"
}
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
class Square: Rectangle {
override var radius: Double {
didSet {
print = Int(radius/5.0)+1
}
}
}
let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
<stdin>:14:18: error: var overrides a 'final' var
override var area: String {
^
<stdin>:7:9: note: overridden declaration is here
var area: String {
^
<stdin>:12:11: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
^
<stdin>:25:14: error: var overrides a 'final' var
override var radius: Double {
^
<stdin>:6:14: note: overridden declaration is here
final var radius = 12.5
Dado que la superclase se declara como 'final' y sus tipos de datos también se declaran como 'finales', el programa no permitirá crear más subclases y arrojará errores.
Las clases, estructuras y enumeraciones una vez declaradas en Swift 4 se inicializan para preparar la instancia de una clase. El valor inicial se inicializa para la propiedad almacenada y también para las nuevas instancias, los valores se inicializan para continuar. La palabra clave para crear la función de inicialización se lleva a cabo mediante el método 'init ()'. El inicializador Swift 4 se diferencia de Objective-C en que no devuelve ningún valor. Su función es verificar la inicialización de instancias recién creadas antes de su procesamiento. Swift 4 también proporciona un proceso de 'desinicialización' para realizar operaciones de administración de memoria una vez que se desasignan las instancias.
Rol de inicializador para propiedades almacenadas
La propiedad almacenada tiene que inicializar las instancias para sus clases y estructuras antes de procesar las instancias. Las propiedades almacenadas utilizan el inicializador para asignar e inicializar valores, lo que elimina la necesidad de llamar a los observadores de propiedades. El inicializador se usa en la propiedad almacenada
Para crear un valor inicial.
Para asignar un valor de propiedad predeterminado dentro de la definición de propiedad.
Para inicializar una instancia para un tipo de datos particular, se usa 'init ()'. No se pasan argumentos dentro de la función init ().
Sintaxis
init() {
//New Instance initialization goes here
}
Ejemplo
struct rectangle {
var length: Double
var breadth: Double
init() {
length = 6
breadth = 12
}
}
var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area of rectangle is 72.0
Aquí, la estructura 'rectángulo' se inicializa con los miembros de longitud y anchura como tipos de datos 'Doble'. El método Init () se utiliza para inicializar los valores de la longitud y el doble de los miembros recién creados. El área del rectángulo se calcula y se devuelve llamando a la función rectángulo.
Establecer valores de propiedad de forma predeterminada
El lenguaje Swift 4 proporciona la función Init () para inicializar los valores de propiedad almacenados. Además, el usuario tiene la posibilidad de inicializar los valores de propiedad de forma predeterminada mientras declara los miembros de la clase o estructura. Cuando la propiedad toma el mismo valor solo en todo el programa, podemos declararlo solo en la sección de declaración en lugar de inicializarlo en init (). Establecer valores de propiedad de forma predeterminada habilita al usuario cuando se define la herencia para clases o estructuras.
struct rectangle {
var length = 6
var breadth = 12
}
var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area of rectangle is 72
Aquí, en lugar de declarar la longitud y la amplitud en init (), los valores se inicializan en la declaración misma.
Inicialización de parámetros
En el lenguaje Swift 4, el usuario tiene la posibilidad de inicializar parámetros como parte de la definición del inicializador usando init ().
struct Rectangle {
var length: Double
var breadth: Double
var area: Double
init(fromLength length: Double, fromBreadth breadth: Double) {
self.length = length
self.breadth = breadth
area = length * breadth
}
init(fromLeng leng: Double, fromBread bread: Double) {
self.length = leng
self.breadth = bread
area = leng * bread
}
}
let ar = Rectangle(fromLength: 6, fromBreadth: 12)
print("area is: \(ar.area)")
let are = Rectangle(fromLeng: 36, fromBread: 12)
print("area is: \(are.area)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area is: 72.0
area is: 432.0
Parámetros locales y externos
Los parámetros de inicialización tienen nombres de parámetros tanto locales como globales similares a los de los parámetros de función y método. La declaración de parámetro local se usa para acceder dentro del cuerpo de inicialización y la declaración de parámetro externo se usa para llamar al inicializador. Los inicializadores de Swift 4 difieren del inicializador de funciones y métodos en que no identifican qué inicializador se utiliza para llamar a qué funciones.
Para superar esto, Swift 4 introduce un nombre externo automático para todos y cada uno de los parámetros en init (). Este nombre externo automático es equivalente al nombre local escrito antes de cada parámetro de inicialización.
struct Days {
let sunday, monday, tuesday: Int
init(sunday: Int, monday: Int, tuesday: Int) {
self.sunday = sunday
self.monday = monday
self.tuesday = tuesday
}
init(daysofaweek: Int) {
sunday = daysofaweek
monday = daysofaweek
tuesday = daysofaweek
}
}
let week = Days(sunday: 1, monday: 2, tuesday: 3)
print("Days of a Week is: \(week.sunday)")
print("Days of a Week is: \(week.monday)")
print("Days of a Week is: \(week.tuesday)")
let weekdays = Days(daysofaweek: 4)
print("Days of a Week is: \(weekdays.sunday)")
print("Days of a Week is: \(weekdays.monday)")
print("Days of a Week is: \(weekdays.tuesday)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Days of a Week is: 1
Days of a Week is: 2
Days of a Week is: 3
Days of a Week is: 4
Days of a Week is: 4
Days of a Week is: 4
Parámetros sin nombres externos
Cuando no se necesita un nombre externo para un guión bajo de inicialización, se usa '_' para anular el comportamiento predeterminado.
struct Rectangle {
var length: Double
init(frombreadth breadth: Double) {
length = breadth * 10
}
init(frombre bre: Double) {
length = bre * 30
}
init(_ area: Double) {
length = area
}
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area is: 180.0
area is: 370.0
area is: 110.0
Tipos de propiedad opcionales
Cuando la propiedad almacenada en alguna instancia no devuelve ningún valor, esa propiedad se declara con un tipo "opcional" que indica que "no se devuelve ningún valor" para ese tipo en particular. Cuando la propiedad almacenada se declara como 'opcional', automáticamente inicializa el valor para que sea 'nulo' durante la inicialización.
struct Rectangle {
var length: Double?
init(frombreadth breadth: Double) {
length = breadth * 10
}
init(frombre bre: Double) {
length = bre * 30
}
init(_ area: Double) {
length = area
}
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)
Modificación de propiedades constantes durante la inicialización
La inicialización también permite al usuario modificar el valor de la propiedad constante. Durante la inicialización, la propiedad de clase permite que sus instancias de clase sean modificadas por la superclase y no por la subclase. Considere, por ejemplo, que en el programa anterior 'longitud' se declara como 'variable' en la clase principal. La siguiente variable de programa 'longitud' se modifica como variable 'constante'.
struct Rectangle {
let length: Double?
init(frombreadth breadth: Double) {
length = breadth * 10
}
init(frombre bre: Double) {
length = bre * 30
}
init(_ area: Double) {
length = area
}
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)
Inicializadores predeterminados
Los inicializadores predeterminados proporcionan una nueva instancia a todas sus propiedades declaradas de clase base o estructura con valores predeterminados.
class defaultexample {
var studname: String?
var stmark = 98
var pass = true
}
var result = defaultexample()
print("result is: \(result.studname)")
print("result is: \(result.stmark)")
print("result is: \(result.pass)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado. -
result is: nil
result is: 98
result is: true
El programa anterior se define con el nombre de clase como 'ejemplo predeterminado'. Tres funciones miembro se inicializan de forma predeterminada como 'studname?' para almacenar valores 'nil', 'stmark' como 98 y 'pass' como valor booleano 'true'. Asimismo, los valores de los miembros de la clase se pueden inicializar de forma predeterminada antes de procesar los tipos de miembros de la clase.
Inicializadores Memberwise para tipos de estructura
Cuando el usuario no proporciona los inicializadores personalizados, los tipos de estructura en Swift 4 recibirán automáticamente el 'inicializador de miembros'. Su función principal es inicializar las nuevas instancias de estructura con la inicialización por miembros predeterminada y luego las propiedades de la nueva instancia se pasan a la inicialización por miembros por nombre.
struct Rectangle {
var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)
print("Area of rectangle is: \(area.length)")
print("Area of rectangle is: \(area.breadth)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Area of rectangle is: 24.0
Area of rectangle is: 32.0
Las estructuras se inicializan de forma predeterminada para sus funciones de pertenencia durante la inicialización para 'longitud' como '100.0' y 'amplitud' como '200.0'. Pero los valores se anulan durante el procesamiento de las variables longitud y amplitud como 24.0 y 32.0.
Delegación de inicializador para tipos de valor
La delegación de inicializadores se define como llamar a inicializadores desde otros inicializadores. Su función principal es actuar como reutilización para evitar la duplicación de código en varios inicializadores.
struct Stmark {
var mark1 = 0.0, mark2 = 0.0
}
struct stdb {
var m1 = 0.0, m2 = 0.0
}
struct block {
var average = stdb()
var result = Stmark()
init() {}
init(average: stdb, result: Stmark) {
self.average = average
self.result = result
}
init(avg: stdb, result: Stmark) {
let tot = avg.m1 - (result.mark1 / 2)
let tot1 = avg.m2 - (result.mark2 / 2)
self.init(average: stdb(m1: tot, m2: tot1), result: result)
}
}
let set1 = block()
print("student result is: \(set1.average.m1, set1.average.m2)
\(set1.result.mark1, set1.result.mark2)")
let set2 = block(average: stdb(m1: 2.0, m2: 2.0),
result: Stmark(mark1: 5.0, mark2: 5.0))
print("student result is: \(set2.average.m1, set2.average.m2)
\(set2.result.mark1, set2.result.mark2)")
let set3 = block(avg: stdb(m1: 4.0, m2: 4.0),
result: Stmark(mark1: 3.0, mark2: 3.0))
print("student result is: \(set3.average.m1, set3.average.m2)
\(set3.result.mark1, set3.result.mark2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)
Reglas para la delegación del inicializador
Tipos de valor | Tipos de clases |
---|---|
La herencia no se admite para tipos de valor como estructuras y enumeraciones. La referencia a otros inicializadores se realiza a través de self.init | Se admite la herencia. Comprueba que todos los valores de propiedad almacenados estén inicializados |
Herencia e inicialización de clases
Los tipos de clase tienen dos tipos de inicializadores para comprobar si las propiedades almacenadas definidas reciben un valor inicial, a saber, inicializadores designados e inicializadores de conveniencia.
Inicializadores designados e inicializadores de conveniencia
Inicializador designado | Inicializador de conveniencia |
---|---|
Considerado como inicializaciones primarias para una clase | Considerado como compatible con la inicialización de una clase |
Todas las propiedades de la clase se inicializan y se llama al inicializador de superclase apropiado para una posterior inicialización | El inicializador designado se llama con un inicializador de conveniencia para crear una instancia de clase para un caso de uso específico o un tipo de valor de entrada |
Se define al menos un inicializador designado para cada clase | No es necesario tener inicializadores de conveniencia obligatorios definidos cuando la clase no requiere inicializadores. |
Init (parámetros) {declaraciones} | conveniencia init (parámetros) {declaraciones} |
Programa para inicializadores designados
class mainClass {
var no1 : Int // local storage
init(no1 : Int) {
self.no1 = no1 // initialization
}
}
class subClass : mainClass {
var no2 : Int // new subclass storage
init(no1 : Int, no2 : Int) {
self.no2 = no2 // initialization
super.init(no1:no1) // redirect to superclass
}
}
let res = mainClass(no1: 10)
let print = subClass(no1: 10, no2: 20)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
res is: 10
res is: 10
res is: 20
Programa para inicializadores de conveniencia
class mainClass {
var no1 : Int // local storage
init(no1 : Int) {
self.no1 = no1 // initialization
}
}
class subClass : mainClass {
var no2 : Int
init(no1 : Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
res is: 20
res is: 30
res is: 50
Herencia y anulación del inicializador
Swift 4 no permite que sus subclases hereden sus inicializadores de superclase para sus tipos de miembros de forma predeterminada. La herencia es aplicable a los inicializadores de clase Super solo hasta cierto punto, lo que se discutirá en Herencia del inicializador automático.
Cuando el usuario necesita tener inicializadores definidos en superclase, el usuario debe definir la subclase con inicializadores como implementación personalizada. Cuando la subclase debe realizar la anulación a la superclase, se debe declarar la palabra clave 'anular'.
class sides {
var corners = 4
var description: String {
return "\(corners) sides"
}
}
let rectangle = sides()
print("Rectangle: \(rectangle.description)")
class pentagon: sides {
override init() {
super.init()
corners = 5
}
}
let bicycle = pentagon()
print("Pentagon: \(bicycle.description)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Rectangle: 4 sides
Pentagon: 5 sides
Inicializadores designados y convenientes en acción
class Planet {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[No Planets]")
}
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")
let noplName = Planet()
print("No Planets like that: \(noplName.name)")
class planets: Planet {
var count: Int
init(name: String, count: Int) {
self.count = count
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, count: 1)
}
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Planet name is: Mercury
No Planets like that: [No Planets]
Inicializador fallido
El usuario debe ser notificado cuando haya fallas en el inicializador al definir una clase, estructura o valores de enumeración. La inicialización de variables a veces se convierte en una falla debido a:
- Valores de parámetro no válidos.
- Ausencia de fuente externa requerida.
- Condición que impide que la inicialización se realice correctamente.
Para detectar las excepciones generadas por el método de inicialización, Swift 4 produce una inicialización flexible llamada 'inicializador fallido' para notificar al usuario que algo pasa desapercibido al inicializar la estructura, clase o miembros de enumeración. La palabra clave para detectar el inicializador fallido es 'init?'. Además, los inicializadores fallidos y no fallidos no se pueden definir con los mismos tipos y nombres de parámetros.
struct studrecord {
let stname: String
init?(stname: String) {
if stname.isEmpty {return nil }
self.stname = stname
}
}
let stmark = studrecord(stname: "Swing")
if let name = stmark {
print("Student name is specified")
}
let blankname = studrecord(stname: "")
if blankname == nil {
print("Student name is left blank")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Student name is specified
Student name is left blank
Inicializadores fallidos para enumeraciones
El lenguaje Swift 4 proporciona la flexibilidad de tener inicializadores Failable para enumeraciones también para notificar al usuario cuando los miembros de la enumeración quedan sin inicializar valores.
enum functions {
case a, b, c, d
init?(funct: String) {
switch funct {
case "one":
self = .a
case "two":
self = .b
case "three":
self = .c
case "four":
self = .d
default:
return nil
}
}
}
let result = functions(funct: "two")
if result != nil {
print("With In Block Two")
}
let badresult = functions(funct: "five")
if badresult == nil {
print("Block Does Not Exist")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
With In Block Two
Block Does Not Exist
Inicializadores fallidos para clases
Un inicializador que falla cuando se declara con enumeraciones y estructuras alerta de un error de inicialización en cualquier circunstancia dentro de su implementación. Sin embargo, el inicializador que falla en las clases alertará sobre la falla solo después de que las propiedades almacenadas se hayan establecido en un valor inicial.
class studrecord {
let studname: String!
init?(studname: String) {
self.studname = studname
if studname.isEmpty { return nil }
}
}
if let stname = studrecord(studname: "Failable Initializers") {
print("Module is \(stname.studname)")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Module is Optional("Failable Initializers")
Anulación de un inicializador fallido
Al igual que en el caso de inicializar, el usuario también tiene la posibilidad de anular un inicializador fallido de superclase dentro de la subclase. La inicialización fallida de superclase también se puede anular con un inicializador no fallido de subclase.
El inicializador de subclase no puede delegar hasta el inicializador de superclase cuando se reemplaza un inicializador de superclase que falla con una inicialización de subclase que no falla.
Un inicializador que no falla nunca puede delegar en un inicializador que falla.
El programa que se proporciona a continuación describe los inicializadores fallidos y no fallidos.
class Planet {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[No Planets]")
}
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")
let noplName = Planet()
print("No Planets like that: \(noplName.name)")
class planets: Planet {
var count: Int
init(name: String, count: Int) {
self.count = count
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, count: 1)
}
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Planet name is: Mercury
No Planets like that: [No Planets]
El init! Inicializador fallido
Swift 4 proporciona 'init?' para definir un inicializador fallable de instancia opcional. Para definir una instancia opcional implícitamente desenvuelta del tipo específico 'init!' está especificado.
struct studrecord {
let stname: String
init!(stname: String) {
if stname.isEmpty {return nil }
self.stname = stname
}
}
let stmark = studrecord(stname: "Swing")
if let name = stmark {
print("Student name is specified")
}
let blankname = studrecord(stname: "")
if blankname == nil {
print("Student name is left blank")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Student name is specified
Student name is left blank
Inicializadores requeridos
Para declarar todas y cada una de las subclases de la palabra clave initialize 'required' debe definirse antes de la función init ().
class classA {
required init() {
var a = 10
print(a)
}
}
class classB: classA {
required init() {
var b = 30
print(b)
}
}
let res = classA()
let print = classB()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
10
30
10
Antes de que se deba desasignar una instancia de clase, se debe llamar a 'desinicializador' para desasignar el espacio de memoria. La palabra clave 'deinit' se utiliza para desasignar los espacios de memoria ocupados por los recursos del sistema. La desinicialización solo está disponible en tipos de clase.
Desinicialización para desasignar espacio de memoria
Swift 4 desasigna automáticamente sus instancias cuando ya no son necesarias, para liberar recursos. Swift 4 maneja la administración de memoria de instancias a través del conteo automático de referencias (ARC), como se describe en Conteo automático de referencias. Normalmente, no es necesario realizar una limpieza manual cuando se desasignan las instancias. Sin embargo, cuando esté trabajando con sus propios recursos, es posible que deba realizar una limpieza adicional usted mismo. Por ejemplo, si crea una clase personalizada para abrir un archivo y escribir algunos datos en él, es posible que deba cerrar el archivo antes de que se desasigne la instancia de la clase.
var counter = 0; // for reference counting
class baseclass {
init() {
counter++;
}
deinit {
counter--;
}
}
var print: baseclass? = baseclass()
print(counter)
print = nil
print(counter)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
1
0
Cuando se omite la instrucción print = nil, los valores del contador se mantienen iguales ya que no se desinicializa.
var counter = 0; // for reference counting
class baseclass {
init() {
counter++;
}
deinit {
counter--;
}
}
var print: baseclass? = baseclass()
print(counter)
print(counter)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
1
1
Las funciones de administración de memoria y su uso se manejan en el lenguaje Swift 4 a través del conteo automático de referencias (ARC). ARC se utiliza para inicializar y desinicializar los recursos del sistema, liberando así los espacios de memoria utilizados por las instancias de clase cuando las instancias ya no son necesarias. ARC realiza un seguimiento de la información sobre las relaciones entre nuestras instancias de código para administrar los recursos de memoria de manera efectiva.
Funciones de ARC
ARC asigna una parte de la memoria para almacenar la información cada vez que init () crea una nueva instancia de clase.
La información sobre el tipo de instancia y sus valores se almacena en la memoria.
Cuando la instancia de la clase ya no es necesaria, automáticamente libera el espacio de memoria mediante deinit () para un mayor almacenamiento y recuperación de la instancia de la clase.
ARC realiza un seguimiento de las propiedades, constantes y variables de las instancias de clase que se refieren actualmente, de modo que deinit () se aplica solo a las instancias no utilizadas.
ARC mantiene una 'fuerte referencia' a esas propiedades de instancia de clase, constantes y variables para restringir la desasignación cuando la instancia de clase está actualmente en uso.
Programa ARC
class StudDetails {
var stname: String!
var mark: Int!
init(stname: String, mark: Int) {
self.stname = stname
self.mark = mark
}
deinit {
print("Deinitialized \(self.stname)")
print("Deinitialized \(self.mark)")
}
}
let stname = "Swift 4"
let mark = 98
print(stname)
print(mark)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Swift 4
98
Instancias de clase ARC Strong Reference Cycles
class studmarks {
let name: String
var stud: student?
init (name: String) {
print("Initializing: \(name)")
self.name = name
}
deinit {
print("Deallocating: \(self.name)")
}
}
class student {
let name: String
var strname: studmarks?
init (name: String) {
print("Initializing: \(name)")
self.name = name
}
deinit {
print("Deallocating: \(self.name)")
}
}
var shiba: studmarks?
var mari: student?
shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")
shiba!.stud = mari
mari!.strname = shiba
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Initializing: Swift 4
Initializing: ARC
Referencias ARC débiles y sin dueño
Las propiedades de tipo de clase tienen dos formas de resolver fuertes ciclos de referencia:
- Referencias débiles
- Referencias sin propietario
Estas referencias se utilizan para permitir que una instancia haga referencia a otras instancias en un ciclo de referencia. Entonces, las instancias pueden referirse a todas y cada una de las instancias en lugar de preocuparse por un ciclo de referencia fuerte. Cuando el usuario sabe que alguna instancia puede devolver valores 'nulos', podemos señalar eso usando una referencia débil. Cuando la instancia va a devolver algo en lugar de nil, entonces declárelo con una referencia sin propietario.
Programa de referencia débil
class module {
let name: String
init(name: String) { self.name = name }
var sub: submodule?
deinit { print("\(name) Is The Main Module") }
}
class submodule {
let number: Int
init(number: Int) { self.number = number }
weak var topic: module?
deinit { print("Sub Module with its topic number is \(number)") }
}
var toc: module?
var list: submodule?
toc = module(name: "ARC")
list = submodule(number: 4)
toc!.sub = list
list!.topic = toc
toc = nil
list = nil
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
ARC Is The Main Module
Sub Module with its topic number is 4
Programa de referencia sin propietario
class student {
let name: String
var section: marks?
init(name: String) {
self.name = name
}
deinit { print("\(name)") }
}
class marks {
let marks: Int
unowned let stname: student
init(marks: Int, stname: student) {
self.marks = marks
self.stname = stname
}
deinit { print("Marks Obtained by the student is \(marks)") }
}
var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
ARC
Marks Obtained by the student is 98
Ciclos de referencia fuertes para cierres
Cuando asignamos un cierre a la propiedad de instancia de clase y al cuerpo del cierre para capturar una instancia particular, puede ocurrir un ciclo de referencia fuerte. La fuerte referencia al cierre se define por 'self.someProperty' o 'self.someMethod ()'. Los ciclos de referencia fuertes se utilizan como tipos de referencia para los cierres.
class HTMLElement {
let samplename: String
let text: String?
lazy var asHTML: () -> String = {
if let text = self.text {
return "<\(self.samplename)>\(text)</\(self.samplename)>"
} else {
return "<\(self.samplename) />"
}
}
init(samplename: String, text: String? = nil) {
self.samplename = samplename
self.text = text
}
deinit {
print("\(samplename) is being deinitialized")
}
}
var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(paragraph!.asHTML())
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
<p>Welcome to Closure SRC</p>
Referencias débiles y sin dueño
Cuando el cierre y la instancia se refieren entre sí, el usuario puede definir la captura en un cierre como una referencia sin dueño. Entonces no permitiría al usuario desasignar la instancia al mismo tiempo. Cuando la instancia en algún momento devuelva un valor 'nulo', defina el cierre con la instancia débil.
class HTMLElement {
let module: String
let text: String?
lazy var asHTML: () -> String = {
[unowned self] in
if let text = self.text {
return "<\(self.module)>\(text)</\(self.module)>"
} else {
return "<\(self.module) />"
}
}
init(module: String, text: String? = nil) {
self.module = module
self.text = text
}
deinit {
print("\(module) the deinit()")
}
}
var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
<Inside>ARC Weak References</Inside>
Inside the deinit()
El proceso de consultar, llamar a propiedades, subíndices y métodos en un opcional que puede ser "nulo" se define como encadenamiento opcional. El encadenamiento opcional devuelve dos valores:
si el opcional contiene un 'valor', llamar a su propiedad, métodos y subíndices relacionados devuelve valores
si el opcional contiene un valor 'nil', todas sus propiedades, métodos y subíndices relacionados devuelven nil
Dado que varias consultas a métodos, propiedades y subíndices se agrupan, la falla en una cadena afectará a toda la cadena y dará como resultado un valor "nulo".
Encadenamiento opcional como alternativa al desenvolvimiento forzado
El encadenamiento opcional se especifica después del valor opcional con '?' para llamar a una propiedad, método o subíndice cuando el valor opcional devuelve algunos valores.
Encadenamiento opcional '?' | Acceso a métodos, propiedades y subíndices Encadenamiento opcional '!' forzar el desenvolvimiento |
? se coloca después del valor opcional para llamar a la propiedad, método o subíndice | ! se coloca después del valor opcional para llamar a la propiedad, método o subíndice para forzar el desenvolvimiento del valor |
Falla graciosamente cuando el opcional es 'nil' | El desenvolvimiento forzado desencadena un error de tiempo de ejecución cuando el opcional es 'nil' |
Programa para encadenamiento opcional con '!'
class ElectionPoll {
var candidate: Pollbooth?
}
lass Pollbooth {
var name = "MP"
}
let cand = ElectionPoll()
let candname = cand.candidate!.name
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
fatal error: unexpectedly found nil while unwrapping an Optional value
0 Swift 4 0x0000000103410b68
llvm::sys::PrintStackTrace(__sFILE*) + 40
1 Swift 4 0x0000000103411054 SignalHandler(int) + 452
2 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 26
3 libsystem_platform.dylib 0x000000000000000b _sigtramp + 1854492939
4 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 1976783636
5 Swift 4 0x0000000102a85c39
llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 329
6 Swift 4 0x0000000102d320b3
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
std::__1::vector<std::__1::basic_string, std::__1::allocator >,
std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&,
char const* const*) + 1523
7 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift
4::CompilerInstance&, std::__1::vector<std::__1::basic_string,
std::__1::allocator >, std::__1::allocator<std::__1::basic_string,
std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptions
const&) + 1066
8 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef,
char const*, void*) + 5275
9 Swift 4 0x0000000102754a6d main + 1677
10 libdyld.dylib 0x00007fff8bb9e5c9 start + 1
11 libdyld.dylib 0x000000000000000c start + 1950751300
Stack dump:
0. Program arguments:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 -
target-cpu core2 -sdk
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/
SDKs/MacOSX10.10.sdk -module-name main
/bin/sh: line 47: 15672 Done cat <<'SWIFT 4'
import Foundation
</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std::
__1::basic_string
El programa anterior declara 'encuesta electoral' como nombre de clase y contiene 'candidato' como función de membresía. La subclase se declara como 'cabina de votación' y 'nombre' como su función de membresía que se inicializa como 'MP'. La llamada a la superclase se inicializa creando una instancia 'cand' con opcional '!'. Dado que los valores no se declaran en su clase base, el valor 'nil' se almacena y devuelve un error fatal por el procedimiento de desenvolvimiento forzado.
Programa para encadenamiento opcional con '?'
class ElectionPoll {
var candidate: Pollbooth?
}
class Pollbooth {
var name = "MP"
}
let cand = ElectionPoll()
if let candname = cand.candidate?.name {
print("Candidate name is \(candname)")
} else {
print("Candidate name cannot be retreived")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Candidate name cannot be retreived
El programa anterior declara 'encuesta electoral' como nombre de clase y contiene 'candidato' como función de membresía. La subclase se declara como 'cabina de votación' y 'nombre' como su función de membresía que se inicializa como 'MP'. La llamada a la superclase se inicializa creando una instancia 'cand' con opcional '?'. Dado que los valores no están declarados en su clase base, el bloque controlador else almacena e imprime en la consola.
Definición de clases de modelo para propiedades de acceso y encadenamiento opcionales
El lenguaje Swift 4 también proporciona el concepto de encadenamiento opcional, para declarar más de una subclases como clases modelo. Este concepto será de gran utilidad para definir modelos complejos y acceder a las propiedades, métodos y subpropiedades de subíndices.
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var street: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let rectname = rectangle()
if let rectarea = rectname.print?.cprint {
print("Area of rectangle is \(rectarea)")
} else {
print("Rectangle Area is not specified")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Rectangle Area is not specified
Métodos de llamada mediante encadenamiento opcional
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("Area of Circle is: \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if circname.print?.circleprint() != nil {
print("Area of circle is specified)")
} else {
print("Area of circle is not specified")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Area of circle is not specified
La función circleprint () declarada dentro de la subclase circle () se llama creando una instancia llamada 'circname'. La función devolverá un valor si contiene algún valor; de lo contrario, devolverá algún mensaje de impresión definido por el usuario marcando la declaración 'if circname.print? .Circleprint ()! = Nil'.
Acceso a subíndices mediante encadenamiento opcional
El encadenamiento opcional se utiliza para establecer y recuperar un valor de subíndice para validar si la llamada a ese subíndice devuelve un valor. '?' se coloca antes de las llaves del subíndice para acceder al valor opcional en el subíndice particular.
Programa 1
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if let radiusName = circname.print?[0].radiusname {
print("The first room name is \(radiusName).")
} else {
print("Radius is not specified.")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Radius is not specified.
En el programa anterior, no se especifican los valores de instancia para la función de pertenencia 'radiusName'. Por lo tanto, la llamada del programa a la función devolverá solo otra parte, mientras que para devolver los valores tenemos que definir los valores para la función de pertenencia particular.
Programa 2
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
if let radiusName = circname.print?[0].radiusname {
print("Radius is measured in \(radiusName).")
} else {
print("Radius is not specified.")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Radius is measured in Units.
En el programa anterior, se especifican los valores de instancia para la función de pertenencia 'radiusName'. Por lo tanto, la llamada del programa a la función ahora devolverá valores.
Acceso a subíndices de tipo opcional
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
var area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]]
area["Radius"]?[1] = 78
area["Circle"]?[1]--
print(area["Radius"]?[0])
print(area["Radius"]?[1])
print(area["Radius"]?[2])
print(area["Radius"]?[3])
print(area["Circle"]?[0])
print(area["Circle"]?[1])
print(area["Circle"]?[2])
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)
Se puede acceder a los valores opcionales de los subíndices haciendo referencia a sus valores de subíndice. Se puede acceder a él como subíndice [0], subíndice [1], etc. Los valores predeterminados del subíndice para 'radio' se asignan primero como [35, 45, 78, 101] y para 'Círculo' [90, 45, 56]] . Luego, los valores del subíndice se cambian como Radio [0] a 78 y Círculo [1] a 45.
Vinculación de múltiples niveles de encadenamiento
También se pueden vincular múltiples subclases con sus métodos, propiedades y subíndices de superclase mediante encadenamiento opcional.
Se pueden vincular múltiples encadenamientos de opcionales -
Si recuperar el tipo no es opcional, el encadenamiento opcional devolverá un valor opcional. Por ejemplo, si String a través del encadenamiento opcional, devolverá String? Valor
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if let radiusName = circname.print?[0].radiusname {
print("The first room name is \(radiusName).")
} else {
print("Radius is not specified.")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Radius is not specified.
En el programa anterior, no se especifican los valores de instancia para la función de pertenencia 'radiusName'. Por lo tanto, la llamada del programa a la función devolverá solo otra parte, mientras que para devolver los valores tenemos que definir los valores para la función de pertenencia particular.
Si el tipo de recuperación ya es opcional, el encadenamiento opcional también devolverá un valor opcional. Por ejemplo, si String? ¿Se accede a través del encadenamiento opcional y devolverá String? Valor..
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
if let radiusName = circname.print?[0].radiusname {
print("Radius is measured in \(radiusName).")
} else {
print("Radius is not specified.")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Radius is measured in Units.
En el programa anterior, se especifican los valores de instancia para la función de pertenencia 'radiusName'. Por lo tanto, la llamada del programa a la función ahora devolverá valores.
Encadenamiento de métodos con valores de retorno opcionales
El encadenamiento opcional también se utiliza para acceder a métodos definidos por subclases.
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("Area of Circle is: \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if circname.print?.circleprint() != nil {
print("Area of circle is specified)")
} else {
print("Area of circle is not specified")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Area of circle is not specified
Para validar el tipo de instancia, entra en juego 'Type Casting' en el idioma Swift 4. Se utiliza para comprobar si el tipo de instancia pertenece a una superclase o subclase en particular o si está definido en su propia jerarquía.
La conversión de tipo Swift 4 proporciona dos operadores 'es' para verificar el tipo de un valor y 'como' y para convertir el valor de tipo a un tipo diferente. La conversión de tipos también comprueba si el tipo de instancia sigue un estándar de conformidad de protocolo particular.
Definición de una jerarquía de clases
La conversión de tipos se utiliza para verificar el tipo de instancias y averiguar si pertenece a un tipo de clase en particular. Además, verifica la jerarquía de clases y sus subclases para verificar y convertir esas instancias para convertirlas en una misma jerarquía.
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
class Chemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [ Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Comprobación de tipo
La verificación de tipos se realiza con el operador 'es'. El operador de verificación de tipo 'es' comprueba si la instancia pertenece a un tipo de subclase en particular y devuelve 'verdadero' si pertenece a esa instancia; de lo contrario, devolverá 'falso'.
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
class Chemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [
Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
if item is Chemistry {
++chemCount
} else if item is Maths {
++mathsCount
}
}
print("Subjects in chemistry contains \(chemCount) topics and maths contains \(mathsCount) topics")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Subjects in chemistry contains 2 topics and maths contains 3 topics
Downcasting
Se puede reducir el tipo de subclase con dos operadores (como? Y como!). 'Como?' devuelve un valor opcional cuando el valor devuelve nulo. Se utiliza para comprobar el abatimiento exitoso.
'¡como!' devuelve el desenvolvimiento forzado como se explica en el encadenamiento opcional cuando el abatimiento devuelve un valor nulo. Se utiliza para desencadenar un error de tiempo de ejecución en caso de falla abatida
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
class Chemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [
Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
if let print = item as? Chemistry {
print("Chemistry topics are: '\(print.physics)', \(print.equations)")
} else if let example = item as? Maths {
print("Maths topics are: '\(example.physics)', \(example.formulae)")
}
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Tipificación: cualquier objeto
La palabra clave 'Cualquiera' se utiliza para representar una instancia que pertenece a cualquier tipo, incluidos los tipos de función.
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
class Chemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [
Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
if let print = item as? Chemistry {
print("Chemistry topics are: '\(print.physics)', \(print.equations)")
} else if let example = item as? Maths {
print("Maths topics are: '\(example.physics)', \(example.formulae)")
}
}
var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))
for print in exampleany {
switch print {
case let someInt as Int:
print("Integer value is \(someInt)")
case let someDouble as Double where someDouble > 0:
print("Pi value is \(someDouble)")
case let someString as String:
print("\(someString)")
case let phy as Chemistry:
print("Topics '\(phy.physics)', \(phy.equations)")
default:
print("None")
}
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz
AnyObject
Para representar la instancia de cualquier tipo de clase, se utiliza la palabra clave 'AnyObject'.
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
class Chemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let saprint: [AnyObject] = [Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in saprint {
if let print = item as? Chemistry {
print("Chemistry topics are: '\(print.physics)', \(print.equations)")
} else if let example = item as? Maths {
print("Maths topics are: '\(example.physics)', \(example.formulae)")
}
}
var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))
for print in exampleany {
switch print {
case let someInt as Int:
print("Integer value is \(someInt)")
case let someDouble as Double where someDouble > 0:
print("Pi value is \(someDouble)")
case let someString as String:
print("\(someString)")
case let phy as Chemistry:
print("Topics '\(phy.physics)', \(phy.equations)")
default:
print("None")
}
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz
La funcionalidad de una clase, estructura o tipo de enumeración existente se puede agregar con la ayuda de extensiones. La funcionalidad de tipo se puede agregar con extensiones, pero no es posible anular la funcionalidad con las extensiones.
Swift Extension Functionalities -
- Adición de propiedades calculadas y propiedades de tipo calculado
- Definición de métodos de instancia y tipo.
- Proporcionar nuevos inicializadores.
- Definición de subíndices
- Definición y uso de nuevos tipos anidados
- Hacer que un tipo existente se ajuste a un protocolo
Las extensiones se declaran con la palabra clave 'extensión'
Sintaxis
extension SomeType {
// new functionality can be added here
}
El tipo existente también se puede agregar con extensiones para convertirlo en un protocolo estándar y su sintaxis es similar a la de las clases o estructuras.
extension SomeType: SomeProtocol, AnotherProtocol {
// protocol requirements is described here
}
Propiedades calculadas
Las propiedades de 'instancia' y 'tipo' calculadas también se pueden ampliar con la ayuda de extensiones.
extension Int {
var add: Int {return self + 100 }
var sub: Int { return self - 10 }
var mul: Int { return self * 10 }
var div: Int { return self / 5 }
}
let addition = 3.add
print("Addition is \(addition)")
let subtraction = 120.sub
print("Subtraction is \(subtraction)")
let multiplication = 39.mul
print("Multiplication is \(multiplication)")
let division = 55.div
print("Division is \(division)")
let mix = 30.add + 34.sub
print("Mixed Type is \(mix)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Addition is 103
Subtraction is 110
Multiplication is 390
Division is 11
Mixed Type is 154
Inicializadores
Swift 4 ofrece la flexibilidad de agregar nuevos inicializadores a un tipo existente mediante extensiones. El usuario puede agregar sus propios tipos personalizados para ampliar los tipos ya definidos y también son posibles opciones de inicialización adicionales. Las extensiones solo admiten init (). deinit () no es compatible con las extensiones.
struct sum {
var num1 = 100, num2 = 200
}
struct diff {
var no1 = 200, no2 = 100
}
struct mult {
var a = sum()
var b = diff()
}
let calc = mult()
print ("Inside mult block \(calc.a.num1, calc.a.num2)")
print("Inside mult block \(calc.b.no1, calc.b.no2)")
let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100))
print("Inside mult block \(memcalc.a.num1, memcalc.a.num2)")
print("Inside mult block \(memcalc.b.no1, memcalc.b.no2)")
extension mult {
init(x: sum, y: diff) {
let X = x.num1 + x.num2
let Y = y.no1 + y.no2
}
}
let a = sum(num1: 100, num2: 200)
print("Inside Sum Block:\( a.num1, a.num2)")
let b = diff(no1: 200, no2: 100)
print("Inside Diff Block: \(b.no1, b.no2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Inside mult block (100, 200)
Inside mult block (200, 100)
Inside mult block (300, 500)
Inside mult block (300, 100)
Inside Sum Block:(100, 200)
Inside Diff Block: (200, 100)
Métodos
Se pueden agregar nuevos métodos de instancia y métodos de tipo a la subclase con la ayuda de extensiones.
extension Int {
func topics(summation: () -> ()) {
for _ in 0..<self {
summation()
}
}
}
4.topics(summation: {
print("Inside Extensions Block")
})
3.topics(summation: {
print("Inside Type Casting Block")
})
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Type Casting Block
Inside Type Casting Block
Inside Type Casting Block
La función topics () toma un argumento de tipo '(suma: () → ())' para indicar que la función no toma ningún argumento y no devolverá ningún valor. Para llamar a esa función varias veces, se inicializa el bloque for y se inicializa la llamada al método con topic ().
Métodos de instancia de mutación
Los métodos de instancia también se pueden modificar cuando se declaran como extensiones.
Los métodos de estructura y enumeración que se modifican a sí mismos o sus propiedades deben marcar el método de instancia como mutante, al igual que los métodos mutados de una implementación original.
extension Double {
mutating func square() {
let pi = 3.1415
self = pi * self * self
}
}
var Trial1 = 3.3
Trial1.square()
print("Area of circle is: \(Trial1)")
var Trial2 = 5.8
Trial2.square()
print("Area of circle is: \(Trial2)")
var Trial3 = 120.3
Trial3.square()
print("Area of circle is: \(Trial3)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Area of circle is: 34.210935
Area of circle is: 105.68006
Area of circle is: 45464.070735
Subíndices
También es posible agregar nuevos subíndices a instancias ya declaradas con extensiones.
extension Int {
subscript(var multtable: Int) -> Int {
var no1 = 1
while multtable > 0 {
no1 *= 10
--multtable
}
return (self / no1) % 10
}
}
print(12[0])
print(7869[1])
print(786543[2])
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
2
6
5
Tipos anidados
Los tipos anidados para instancias de clase, estructura y enumeración también se pueden ampliar con la ayuda de extensiones.
extension Int {
enum calc {
case add
case sub
case mult
case div
case anything
}
var print: calc {
switch self {
case 0:
return .add
case 1:
return .sub
case 2:
return .mult
case 3:
return .div
default:
return .anything
}
}
}
func result(numb: [Int]) {
for i in numb {
switch i.print {
case .add:
print(" 10 ")
case .sub:
print(" 20 ")
case .mult:
print(" 30 ")
case .div:
print(" 40 ")
default:
print(" 50 ")
}
}
}
result(numb: [0, 1, 2, 3, 4, 7])
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
10
20
30
40
50
50
Los protocolos proporcionan un modelo de métodos, propiedades y otras funciones de requisitos. Simplemente se describe como un esqueleto de métodos o propiedades en lugar de implementación. La implementación de métodos y propiedades se puede realizar además mediante la definición de clases, funciones y enumeraciones. La conformidad de un protocolo se define como los métodos o propiedades que satisfacen los requisitos del protocolo.
Sintaxis
Los protocolos también siguen una sintaxis similar a la de las clases, estructuras y enumeraciones:
protocol SomeProtocol {
// protocol definition
}
Los protocolos se declaran después de los nombres de clase, estructura o tipo de enumeración. También son posibles declaraciones de protocolo único y múltiple. Si se definen varios protocolos, deben estar separados por comas.
struct SomeStructure: Protocol1, Protocol2 {
// structure definition
}
Cuando se debe definir un protocolo para la superclase, el nombre del protocolo debe seguir al nombre de la superclase con una coma.
class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
// class definition
}
Requisitos de propiedad y método
El protocolo se utiliza para especificar una propiedad de tipo de clase particular o una propiedad de instancia. Solo especifica el tipo o la propiedad de instancia por sí sola en lugar de especificar si es una propiedad almacenada o calculada. Además, se utiliza para especificar si la propiedad es 'obtenible' o 'configurable'.
Los requisitos de propiedad se declaran mediante la palabra clave 'var' como variables de propiedad. {get set} se usa para declarar propiedades obtenibles y configurables después de su declaración de tipo. Gettable es mencionado por la propiedad {get} después de su declaración de tipo.
protocol classa {
var marks: Int { get set }
var result: Bool { get }
func attendance() -> String
func markssecured() -> String
}
protocol classb: classa {
var present: Bool { get set }
var subject: String { get set }
var stname: String { get set }
}
class classc: classb {
var marks = 96
let result = true
var present = false
var subject = "Swift 4 Protocols"
var stname = "Protocols"
func attendance() -> String {
return "The \(stname) has secured 99% attendance"
}
func markssecured() -> String {
return "\(stname) has scored \(marks)"
}
}
let studdet = classc()
studdet.stname = "Swift 4"
studdet.marks = 98
studdet.markssecured()
print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
98
true
false
Swift 4 Protocols
Swift 4
Requisitos del método de mutación
protocol daysofaweek {
mutating func print()
}
enum days: daysofaweek {
case sun, mon, tue, wed, thurs, fri, sat
mutating func print() {
switch self {
case sun:
self = sun
print("Sunday")
case mon:
self = mon
print("Monday")
case tue:
self = tue
print("Tuesday")
case wed:
self = wed
print("Wednesday")
case mon:
self = thurs
print("Thursday")
case tue:
self = fri
print("Friday")
case sat:
self = sat
print("Saturday")
default:
print("NO Such Day")
}
}
}
var res = days.wed
res.print()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Wednesday
Requisitos del inicializador
Swing permite al usuario inicializar protocolos para seguir una conformidad de tipo similar a la de los inicializadores normales.
Sintaxis
protocol SomeProtocol {
init(someParameter: Int)
}
Por ejemplo
protocol tcpprotocol {
init(aprot: Int)
}
Implementaciones de clase de requisitos de inicializador de protocolo
El inicializador designado o de conveniencia permite al usuario inicializar un protocolo para cumplir con su estándar mediante la palabra clave reservada 'requerida'.
class SomeClass: SomeProtocol {
required init(someParameter: Int) {
// initializer implementation statements
}
}
protocol tcpprotocol {
init(aprot: Int)
}
class tcpClass: tcpprotocol {
required init(aprot: Int) {
}
}
La conformidad del protocolo está asegurada en todas las subclases para la implementación explícita o heredada mediante el modificador "requerido".
Cuando una subclase anula su requisito de inicialización de superclase, se especifica mediante la palabra clave modificadora 'anular'.
protocol tcpprotocol {
init(no1: Int)
}
class mainClass {
var no1: Int // local storage
init(no1: Int) {
self.no1 = no1 // initialization
}
}
class subClass: mainClass, tcpprotocol {
var no2: Int
init(no1: Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
required override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
res is: 20
res is: 30
res is: 50
Protocolos como tipos
En lugar de implementar funcionalidades en un protocolo, se utilizan como tipos para funciones, clases, métodos, etc.
Se puede acceder a los protocolos como tipos en:
Función, método o inicialización como parámetro o tipo de retorno
Constante, variable o propiedad
Matrices, diccionarios u otros contenedores como elementos
protocol Generator {
typealias members
func next() -> members?
}
var items = [10,20,30].generate()
while let x = items.next() {
print(x)
}
for lists in map([1,2,3], {i in i*5}) {
print(lists)
}
print([100,200,300])
print(map([1,2,3], {i in i*10}))
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]
Adición de conformidad de protocolo con una extensión
El tipo existente puede adoptarse y ajustarse a un nuevo protocolo mediante el uso de extensiones. Se pueden agregar nuevas propiedades, métodos y subíndices a los tipos existentes con la ayuda de extensiones.
protocol AgeClasificationProtocol {
var age: Int { get }
func agetype() -> String
}
class Person {
let firstname: String
let lastname: String
var age: Int
init(firstname: String, lastname: String) {
self.firstname = firstname
self.lastname = lastname
self.age = 10
}
}
extension Person : AgeClasificationProtocol {
func fullname() -> String {
var c: String
c = firstname + " " + lastname
return c
}
func agetype() -> String {
switch age {
case 0...2:
return "Baby"
case 2...12:
return "Child"
case 13...19:
return "Teenager"
case let x where x > 65:
return "Elderly"
default:
return "Normal"
}
}
}
Herencia del protocolo
Swift 4 permite que los protocolos hereden propiedades de sus propiedades definidas. Es similar a la herencia de clases, pero con la opción de listar varios protocolos heredados separados por comas.
protocol classa {
var no1: Int { get set }
func calc(sum: Int)
}
protocol result {
func print(target: classa)
}
class student2: result {
func print(target: classa) {
target.calc(sum: 1)
}
}
class classb: result {
func print(target: classa) {
target.calc(sum: 5)
}
}
class student: classa {
var no1: Int = 10
func calc(sum: Int) {
no1 -= sum
print("Student attempted \(sum) times to pass")
if no1 <= 0 {
print("Student is absent for exam")
}
}
}
class Player {
var stmark: result!
init(stmark: result) {
self.stmark = stmark
}
func print(target: classa) {
stmark.print(target: target)
}
}
var marks = Player(stmark: student2())
var marksec = student()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
marks.stmark = classb()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 5 times to pass
Student attempted 5 times to pass
Student is absent for exam
Student attempted 5 times to pass
Student is absent for exam
Protocolos de clase única
Cuando se definen protocolos y el usuario desea definir un protocolo con clases, se debe agregar definiendo primero la clase seguida de la lista de herencia del protocolo.
protocol tcpprotocol {
init(no1: Int)
}
class mainClass {
var no1: Int // local storage
init(no1: Int) {
self.no1 = no1 // initialization
}
}
class subClass: mainClass, tcpprotocol {
var no2: Int
init(no1: Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
required override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
res is: 20
res is: 30
res is: 50
Composición del protocolo
Swift 4 permite llamar a múltiples protocolos a la vez con la ayuda de la composición del protocolo.
Sintaxis
protocol<SomeProtocol, AnotherProtocol>
Ejemplo
protocol stname {
var name: String { get }
}
protocol stage {
var age: Int { get }
}
struct Person: stname, stage {
var name: String
var age: Int
}
func print(celebrator: stname & stage) {
print("\(celebrator.name) is \(celebrator.age) years old")
}
let studname = Person(name: "Priya", age: 21)
print(studname)
let stud = Person(name: "Rehan", age: 29)
print(stud)
let student = Person(name: "Roshan", age: 19)
print(student)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)
Comprobación de la conformidad del protocolo
La conformidad del protocolo se prueba mediante operadores 'is' y 'as' similares a los de la fundición de tipos.
El operador is devuelve verdadero si una instancia cumple con el estándar del protocolo y devuelve falso si falla.
los as? La versión del operador downcast devuelve un valor opcional del tipo de protocolo, y este valor es nulo si la instancia no se ajusta a ese protocolo.
La versión as del operador abatido obliga al abatido al tipo de protocolo y desencadena un error de tiempo de ejecución si el abatimiento no tiene éxito.
import Foundation
@objc protocol rectangle {
var area: Double { get }
}
@objc class Circle: rectangle {
let pi = 3.1415927
var radius: Double
var area: Double { return pi * radius * radius }
init(radius: Double) { self.radius = radius }
}
@objc class result: rectangle {
var area: Double
init(area: Double) { self.area = area }
}
class sides {
var rectsides: Int
init(rectsides: Int) { self.rectsides = rectsides }
}
let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]
for object in objects {
if let objectWithArea = object as? rectangle {
print("Area is \(objectWithArea.area)")
} else {
print("Rectangle area is not defined")
}
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Area is 12.5663708
Area is 198.0
Rectangle area is not defined
El lenguaje Swift 4 proporciona funciones "genéricas" para escribir funciones y tipos flexibles y reutilizables. Los genéricos se utilizan para evitar la duplicación y proporcionar abstracción. Las bibliotecas estándar de Swift 4 se crean con código genérico. Los tipos Swift 4s 'Arrays' y 'Dictionary' pertenecen a colecciones genéricas. Con la ayuda de matrices y diccionarios, las matrices se definen para contener valores 'Int' y valores de 'Cadena' o cualquier otro tipo.
func exchange(a: inout Int, b: inout Int) {
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping values are: \(numb1) and \(numb2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Before Swapping values are: 100 and 200
After Swapping values are: 200 and 100
Funciones genéricas: parámetros de tipo
Las funciones genéricas se pueden utilizar para acceder a cualquier tipo de datos como 'Int' o 'String'.
func exchange<T>(a: inout T, b: inout T) {
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")
var str1 = "Generics"
var str2 = "Functions"
print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics
La función exchange () se usa para intercambiar valores que se describen en el programa anterior y <T> se usa como parámetro de tipo. Por primera vez, se llama a la función exchange () para devolver valores 'Int' y la segunda llamada a la función exchange () devolverá valores 'String'. Se pueden incluir varios tipos de parámetros dentro de los corchetes angulares separados por comas.
Los parámetros de tipo se denominan definidos por el usuario para conocer el propósito del parámetro de tipo que contiene. Swift 4 proporciona <T> como nombre de parámetro de tipo genérico. Sin embargo, los parámetros de tipo como Matrices y Diccionarios también se pueden nombrar como clave, valor para identificar que pertenecen al tipo 'Diccionario'.
struct TOS<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]
Ampliación de un tipo genérico
La extensión de la propiedad de la pila para conocer la parte superior del elemento se incluye con la palabra clave 'extensión'.
struct TOS<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
extension TOS {
var first: T? {
return items.isEmpty ? nil : items[items.count - 1]
}
}
if let first = tos.first {
print("The top item on the stack is \(first).")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
["Swift 4"]
["Swift 4", "Generics"]
["Swift 4", "Generics", "Type Parameters"]
["Swift 4", "Generics", "Type Parameters", "Naming Type Parameters"]
The top item on the stack is Naming Type Parameters.
Restricciones de tipo
El lenguaje Swift 4 permite 'restricciones de tipo' para especificar si el parámetro de tipo hereda de una clase específica o para garantizar el estándar de conformidad del protocolo.
func exchange<T>(a: inout T, b: inout T) {
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")
var str1 = "Generics"
var str2 = "Functions"
print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics
Tipos asociados
Swift 4 permite que los tipos asociados se declaren dentro de la definición del protocolo mediante la palabra clave 'associatedtype'.
protocol Container {
associatedtype ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct TOS<T>: Container {
// original Stack<T> implementation
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item: item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]
Donde las cláusulas
Las restricciones de tipo permiten al usuario definir requisitos sobre los parámetros de tipo asociados con una función o tipo genérico. Para definir los requisitos para los tipos asociados, las cláusulas 'donde' se declaran como parte de la lista de parámetros de tipo. La palabra clave 'donde' se coloca inmediatamente después de la lista de parámetros de tipo seguida de restricciones de tipos asociados, relaciones de igualdad entre tipos y tipos asociados.
protocol Container {
associatedtype ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
// original Stack<T> implementation
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item: item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2) -> Bool {
// check that both containers contain the same number of items
if someContainer.count != anotherContainer.count {
return false
}
// check each pair of items to see if they are equivalent
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
// all items match, so return true
return true
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Where Clause")
print(tos.items)
var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]
Para restringir el acceso a bloques de código, módulos y abstracción se realiza a través del control de acceso. Se puede acceder a clases, estructuras y enumeraciones según sus propiedades, métodos, inicializadores y subíndices mediante mecanismos de control de acceso. Las constantes, variables y funciones en un protocolo están restringidas y se permite el acceso como global y local a través del control de acceso. El control de acceso aplicado a propiedades, tipos y funciones puede denominarse "entidades".
El modelo de control de acceso se basa en módulos y archivos fuente.
El módulo se define como una sola unidad de distribución de código y se puede importar utilizando la palabra clave 'importar'. Un archivo fuente se define como un solo archivo de código fuente dentro de un módulo para acceder a múltiples tipos y funciones.
Swift 4 language proporciona tres niveles de acceso diferentes. Son de acceso Público, Interno y Privado.
S. No | Niveles de acceso y definición |
---|---|
1 | Public Permite que las entidades se procesen en cualquier archivo de origen desde su módulo de definición, un archivo de origen de otro módulo que importa el módulo de definición. |
2 | Internal Permite que las entidades se utilicen dentro de cualquier archivo fuente desde su módulo de definición, pero no en ningún archivo fuente fuera de ese módulo. |
3 | Private Restringe el uso de una entidad a su propio archivo fuente de definición. El acceso privado juega un papel importante para ocultar los detalles de implementación de una funcionalidad de código específico. |
Sintaxis
public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}
Control de acceso para tipos de funciones
Algunas funciones pueden tener argumentos declarados dentro de la función sin ningún valor de retorno. El siguiente programa declara ayb como argumentos de la función sum (). Dentro de la función en sí, los valores para los argumentos ayb se pasan invocando la llamada a la función sum () y sus valores se imprimen eliminando así los valores de retorno. Para que el tipo de retorno de la función sea privado, declare el nivel de acceso general de la función con el modificador privado.
private func sum(a: Int, b: Int) {
let a = a + b
let b = a - b
print(a, b)
}
sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
30 20
50 40
30 24
Control de acceso para tipos de enumeración
public enum Student {
case Name(String)
case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
print("Student name is: \(studName).")
case .Mark(let Mark1, let Mark2, let Mark3):
print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Student Marks are: 98,97,95
La enumeración en el idioma Swift 4 recibe automáticamente el mismo nivel de acceso para casos individuales de una enumeración. Considere, por ejemplo, acceder al nombre de los estudiantes y las marcas aseguradas en tres asignaturas. El nombre de enumeración se declara como estudiante y los miembros presentes en la clase de enumeración son nombres que pertenecen al tipo de datos de cadena, las marcas se representan como mark1, mark2 y mark3 del tipo de datos Integer. Para acceder al nombre del estudiante o las notas que ha obtenido. Ahora, el caso del interruptor imprimirá el nombre del estudiante si se ejecuta ese bloque de caso, de lo contrario, imprimirá las marcas obtenidas por el estudiante. Si ambas condiciones fallan, se ejecutará el bloque predeterminado.
Control de acceso para subclases
Swift 4 permite al usuario crear una subclase de cualquier clase a la que se pueda acceder en el contexto de acceso actual. Una subclase no puede tener un nivel de acceso más alto que su superclase. El usuario no puede escribir una subclase pública de una superclase interna.
public class cricket {
internal func printIt() {
print("Welcome to Swift 4 Super Class")
}
}
internal class tennis: cricket {
override internal func printIt() {
print("Welcome to Swift 4 Sub Class")
}
}
let cricinstance = cricket()
cricinstance.printIt()
let tennisinstance = tennis()
tennisinstance.printIt()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Welcome to Swift Super Class
Welcome to Swift Sub Class
Control de acceso para constantes, variables, propiedades y subíndices
La constante, variable o propiedad de Swift 4 no se puede definir como pública más que su tipo. No es válido escribir una propiedad pública con un tipo privado. De manera similar, un subíndice no puede ser más público que su índice o tipo de retorno.
Cuando una constante, variable, propiedad o subíndice hace uso de un tipo privado, la constante, variable, propiedad o subíndice también debe marcarse como privado:
private var privateInstance = SomePrivateClass()
Getters y Setters
Los captadores y definidores de constantes, variables, propiedades y subíndices reciben automáticamente el mismo nivel de acceso que la constante, variable, propiedad o subíndice al que pertenecen.
class Samplepgm {
var counter: Int = 0{
willSet(newTotal) {
print("Total Counter is: \(newTotal)")
}
didSet {
if counter > oldValue {
print("Newly Added Counter \(counter - oldValue)")
}
}
}
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
Control de acceso para inicializadores e inicializadores predeterminados
A los inicializadores personalizados se les puede asignar un nivel de acceso menor o igual al tipo que inicializan. Un inicializador obligatorio debe tener el mismo nivel de acceso que la clase a la que pertenece. Los tipos de parámetros de un inicializador no pueden ser más privados que el propio nivel de acceso del inicializador.
Para declarar todas y cada una de las subclases de la palabra clave initialize 'required' debe definirse antes de la función init ().
class classA {
required init() {
let a = 10
print(a)
}
}
class classB: classA {
required init() {
let b = 30
print(b)
}
}
let res = classA()
let print = classB()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
10
30
10
Un inicializador predeterminado tiene el mismo nivel de acceso que el tipo que inicializa, a menos que ese tipo esté definido como público. Cuando la inicialización predeterminada se define como pública, se considera interna. Cuando el usuario necesita que un tipo público se pueda inicializar con un inicializador sin argumentos en otro módulo, proporcione explícitamente un inicializador sin argumentos público como parte de la definición del tipo.
Control de acceso para protocolos
Cuando definimos un nuevo protocolo para heredar funcionalidades de un protocolo existente, ambos deben declararse con los mismos niveles de acceso para heredar las propiedades del otro. El control de acceso de Swift 4 no permitirá a los usuarios definir un protocolo "público" que herede de un protocolo "interno".
public protocol tcpprotocol {
init(no1: Int)
}
public class mainClass {
var no1: Int // local storage
init(no1: Int) {
self.no1 = no1 // initialization
}
}
class subClass: mainClass, tcpprotocol {
var no2: Int
init(no1: Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
required override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
res is: 20
res is: 30
res is: 50
Control de acceso para extensiones
Swift 4 no permite a los usuarios proporcionar un modificador de nivel de acceso explícito para una extensión cuando el usuario usa esa extensión para agregar conformidad con el protocolo. El nivel de acceso predeterminado para cada implementación de requisitos de protocolo dentro de la extensión se proporciona con su propio nivel de acceso de protocolo.
Control de acceso para genéricos
Los genéricos permiten al usuario especificar niveles mínimos de acceso para acceder a las restricciones de tipo en sus parámetros de tipo.
public struct TOS<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]
Control de acceso para alias de tipo
El usuario puede definir alias de tipos para tratar distintos tipos de control de acceso. El usuario puede definir el mismo nivel de acceso o diferentes niveles de acceso. Cuando el alias de tipo es 'privado', sus miembros asociados pueden declararse como 'privados, internos de tipo público'. Cuando el alias de tipo es público, los miembros no pueden ser alias como un nombre 'interno' o 'privado'
Los alias de tipo que defina se tratan como tipos distintos a los efectos del control de acceso. Un alias de tipo puede tener un nivel de acceso menor o igual que el nivel de acceso del tipo al que alias. Por ejemplo, un alias de tipo privado puede alias un tipo privado, interno o público, pero un alias de tipo público no puede alias un tipo interno o privado.
public protocol Container {
associatedtype ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
// original Stack<T> implementation
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item: item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2) -> Bool {
// check that both containers contain the same number of items
if someContainer.count != anotherContainer.count {
return false
}
// check each pair of items to see if they are equivalent
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
// all items match, so return true
return true
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Where Clause")
print(tos.items)
var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]
Codificación y decodificación rápida
Swift 4 presenta un nuevo Codable Protocolo, que le permite serializar y deserializar tipos de datos personalizados sin escribir ningún código especial y sin tener que preocuparse por perder sus tipos de valor.
struct Language: Codable {
var name: String
var version: Int
}
let swift = Language(name: "Swift", version: 4)
let java = Language(name: "java", version: 8)
let R = Language(name: "R", version: 3
Tenga en cuenta que Langauage se ajusta al Protocolo de codificación. Ahora lo convertiremos en una representación de datos Json usando una línea simple.
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
//Perform some operations on this value.
}
Swift codificará automáticamente todos los valores dentro de su tipo de datos.
Puede decodificar los datos utilizando la función Decodificador como
let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
//Perform some operations on this value.
}
Tanto JSONEncoder como su contraparte de la lista de propiedades PropertyListEncoder tienen muchas opciones para personalizar cómo funcionan.