En el artículo anterior, exploramos los conceptos básicos de las funciones en Swift. Las funciones, sin embargo, tienen mucho más que ofrecer. En este artículo, continuamos nuestra exploración de funciones y analizamos los parámetros de función, el anidamiento y los tipos..
Revisemos uno de los ejemplos del artículo anterior. los PrintMessage (mensaje :)
función define un parámetro, mensaje
.
func printMessage (message: String) print (message)
Le asignamos un nombre, mensaje
, al parámetro y usar este nombre cuando llamamos a la función.
printMessage (mensaje: "¡Hola mundo!")
Pero tenga en cuenta que también usamos el mismo nombre para hacer referencia al valor del parámetro en el cuerpo de la función.
func printMessage (message: String) print (message)
En Swift, un parámetro siempre tiene un local nombre del parámetro, y opcionalmente tiene un externo Nombre del parámetro. En el ejemplo, los nombres de parámetros locales y externos son idénticos.
A partir de Swift 3, el equipo de Swift ha definido un conjunto claro de directrices API. No voy a entrar en esas directrices en este tutorial, pero quiero señalar que la definición de la PrintMessage (mensaje :)
La función se desvía de esas pautas. El nombre de la función contiene la palabra mensaje
, y el parámetro también se nombra mensaje
. En otras palabras, nos estamos repitiendo..
Sería más elegante si pudiéramos invocar el PrintMessage (mensaje :)
funcionar sin el mensaje
palabra clave. Esto es lo que tengo en mente..
printMessage ("Hola, mundo!")
Esto es posible, y está más en línea con las directrices de Swift API. Pero, ¿qué es diferente? La diferencia es fácil de detectar si echamos un vistazo a la definición de función actualizada. El ejemplo actualizado también revela más sobre la anatomía de las funciones en Swift.
func printMessage (_ message: String) print (message)
En una definición de función, cada parámetro está definido por un nombre de parámetro externo, un nombre de parámetro local, dos puntos y el tipo de parámetro. Si los nombres de los parámetros locales y externos son idénticos, solo escribimos el nombre del parámetro una vez. Es por eso que el primer ejemplo define un nombre de parámetro, mensaje
.
Si no queremos asignar un nombre de parámetro externo a un parámetro, usamos el _
, un guion bajo Esto le informa al compilador que el parámetro no tiene un nombre de parámetro externo, y eso significa que podemos omitir el nombre del parámetro cuando se invoca la función.
Objective-C es conocido por sus largos nombres de métodos. Si bien esto puede parecer torpe y poco elegante para los forasteros, hace que los métodos sean fáciles de entender y, si se eligen bien, muy descriptivos. El equipo Swift entendió esta ventaja e introdujo nombres de parámetros externos desde el primer día.
Cuando una función acepta varios parámetros, no siempre es obvio qué argumento corresponde a qué parámetro. Eche un vistazo al siguiente ejemplo para comprender mejor el problema. Observe que los parámetros no tienen un nombre de parámetro externo.
func power (_ a: Int, _ b: Int) -> Int var result = a para _ en 1 ...los
poder(_:_:)
función eleva el valor deuna
por el exponentesegundo
. Ambos parámetros son de tipoEn t
. Mientras que la mayoría de las personas pasarán intuitivamente el valor base como primer argumento y el exponente como segundo argumento, esto no queda claro en el tipo, nombre o firma de la función. Como vimos en el artículo anterior, invocar la función es sencillo.potencia (2, 3)Para evitar confusiones, podemos asignar nombres externos a los parámetros de una función. Luego podemos usar estos nombres externos cuando se llama a la función para indicar inequívocamente qué argumento corresponde a qué parámetro. Eche un vistazo al ejemplo actualizado a continuación..
Potencia func (base a: Int, exponente b: Int) -> Int var resultado = a para _ en 1 ...Tenga en cuenta que el cuerpo de la función no ha cambiado desde que los nombres locales no han cambiado. Sin embargo, cuando invocamos la función actualizada, la diferencia es clara y el resultado es menos confuso..
potencia (base: 2, exponente: 3)Mientras que los tipos de ambas funciones son idénticos,
(Int, Int) -> Int
, Las funciones son diferentes. En otras palabras, la segunda función no es una redeclaración de la primera función. La sintaxis para invocar la segunda función puede recordarle Objective-C. Los argumentos no solo están claramente descritos, sino que la combinación de funciones y nombres de parámetros también describe el propósito de la función..En algunos casos, desea utilizar el mismo nombre para el nombre del parámetro local y externo. Esto es posible, y no es necesario escribir el nombre del parámetro dos veces. En el siguiente ejemplo, usamos
base
yexponente
como los nombres de los parámetros locales y externos.Potencia de la función (base: Int, exponente: Int) -> Int var resultado = base para _ en 1 ...Al definir un nombre para cada parámetro, el nombre del parámetro sirve como el nombre local y externo del parámetro. Esto también significa que necesitamos actualizar el cuerpo de la función.
Es importante tener en cuenta que al proporcionar un nombre externo para un parámetro, debe usar ese nombre al invocar la función. Esto nos lleva a los valores por defecto..
Valores predeterminados
Cubrimos los valores predeterminados de los parámetros en el artículo anterior. Esta es la función que definimos en ese artículo..
func printDate (fecha: Fecha, formato: String = "YY / MM / dd") -> String let dateFormatter = DateFormatter () dateFormatter.dateFormat = format return dateFormatter.string (from: date)Qué sucede si no definimos un nombre de parámetro externo para el segundo parámetro, que tiene un valor predeterminado?
func printDate (fecha: Fecha, _ formato: String = "YY / MM / dd") -> String let dateFormatter = DateFormatter () dateFormatter.dateFormat = format return dateFormatter.string (from: date))Al compilador no parece importarle. ¿Pero es esto lo que queremos? Es mejor definir un nombre de parámetro externo a parámetros opcionales (parámetros con un valor predeterminado) para evitar confusiones y ambigüedades.
Observe que nos estamos repitiendo nuevamente en el ejemplo anterior. No es necesario definir un nombre de parámetro externo para el
fecha
parámetro. El siguiente ejemplo muestra lo queprintDate (_: format :)
La función se vería como si seguimos las directrices de Swift API.func printDate (_ date: Date, format: String = "YY / MM / dd") -> String let dateFormatter = DateFormatter () dateFormatter.dateFormat = format return dateFormatter.string (from: date))Ahora podemos invocar el
formatDate (_: format :)
funciona sin usar elfecha
Etiqueta para el primer parámetro y con un formato de fecha opcional..printDate (Date ()) printDate (Date (), format: "dd / MM / YY")2. Parámetros y mutabilidad.
Repasemos el primer ejemplo de este tutorial, el
imprimir mensaje (_ :)
función. ¿Qué pasa si cambiamos el valor de lamensaje
parámetro dentro del cuerpo de la función?func printMessage (_ message: String) message = "Print: \ (message)" print (message)El compilador no tarda mucho en comenzar a quejarse.
Los parámetros de una función son constantes. En otras palabras, si bien podemos acceder a los valores de los parámetros de la función, no podemos cambiar su valor. Para evitar esta limitación, declaramos una variable en el cuerpo de la función y usamos esa variable en su lugar.
func printMessage (_ message: String) var message = message message = "Print: \ (message)" print (mensaje)3. Parámetros variables
Si bien el término puede sonar extraño al principio, los parámetros variables son comunes en la programación. Un parámetro variadic es un parámetro que acepta cero o más valores. Los valores deben ser del mismo tipo. El uso de parámetros variables en Swift es trivial, como lo ilustra el siguiente ejemplo.
func sum (_ args: Int…) -> Int var resultado = 0 para a en args resultado + = a retorno resultado suma (1, 2, 3, 4)La sintaxis es fácil de entender. Para marcar un parámetro como variadic, agregue tres puntos al tipo de parámetro. En el cuerpo de la función, el parámetro variadic es accesible como una matriz. En el ejemplo anterior,
args
es una matriz deEn t
valores.Debido a que Swift necesita saber qué argumentos corresponden a qué parámetros, se requiere que un parámetro variadic sea el último parámetro. También implica que una función puede tener como máximo un parámetro variadic.
Lo anterior también se aplica si una función tiene parámetros con valores predeterminados. El parámetro variadic siempre debe ser el último parámetro..
4. Parámetros de entrada-salida
Anteriormente en este tutorial, aprendiste que los parámetros de una función son constantes. Si desea pasar un valor a una función, modifíquelo en la función y vuelva a pasarlo fuera de la función, los parámetros de entrada y salida son lo que necesita.
El siguiente ejemplo muestra un ejemplo de cómo funcionan los parámetros de entrada y salida en Swift y cómo se ve la sintaxis.
func prefixString (_ string: inout String, con prefix: String) string = prefix + stringDefinimos el primer parámetro como un parámetro de entrada-salida agregando el
En fuera
palabra clave. El segundo parámetro es un parámetro regular con un nombre externo dewithString
y un nombre local deprefijo
. ¿Cómo invocamos esta función??var input = "world!" prefixString (y entrada, con: "Hola")Declaramos una variable.,
entrada
, de tipoCuerda
y pasarlo a laprefixString (_: con :)
función. El segundo parámetro es una cadena literal. Al invocar la función, el valor de laentrada
variable se convierteHola Mundo!
. Tenga en cuenta que el primer argumento es prefijado con un ampersand,Y
, para indicar que es un parámetro de entrada-salida.No hace falta decir que las constantes y los literales no se pueden pasar como parámetros in-out. El compilador arroja un error cuando haces lo que se ilustra en los siguientes ejemplos.
Es evidente que los parámetros de entrada / salida no pueden tener valores predeterminados o pueden ser variados. Si olvida estos detalles, el compilador le recuerda amablemente con un error..
5. Anidación
En C y Objective-C, las funciones y los métodos no se pueden anidar. En Swift, sin embargo, las funciones anidadas son bastante comunes. Las funciones que vimos en este y en el artículo anterior son ejemplos de funciones globales, se definen en el ámbito global.
Cuando definimos una función dentro de una función global, nos referimos a esa función como una función anidada. Una función anidada tiene acceso a los valores definidos en su función envolvente. Eche un vistazo al siguiente ejemplo para entenderlo mejor..
func printMessage (_ message: String) let a = "hello world" func printHelloWorld () print (a)Si bien las funciones de este ejemplo no son muy útiles, ilustran la idea de funciones anidadas y la captura de valores. los
printHelloWorld ()
La función solo es accesible desde el interior delimprimir mensaje (_ :)
función.Como se ilustra en el ejemplo, la
printHelloWorld ()
La función tiene acceso a la constante.una
. El valor es capturado por la función anidada y, por lo tanto, es accesible desde dentro de esa función. Swift se encarga de capturar los valores, incluida la administración de la memoria de esos valores..6. Tipos de funciones
Funciones como parámetros
En el artículo anterior, tratamos brevemente los tipos de funciones. Una función tiene un tipo particular, compuesto por los tipos de parámetros de la función y su tipo de retorno. los
imprimir mensaje (_ :)
La función, por ejemplo, es de tipo.(Cuerda) -> ()
. Recuérdalo()
simbolizaVacío
, que es equivalente a una tupla vacía.Debido a que cada función tiene un tipo, es posible definir una función que acepte otra función como parámetro. El siguiente ejemplo muestra cómo funciona esto..
func printMessage (_ message: String) print (message) func printMessage (_ message: String, con la función: (String) -> ()) function (message) let myMessage = "Hello, world!" printMessage (myMessage, con: printMessage)los
PrintMessage (_: con :)
La función acepta una cadena como su primer parámetro y una función de tipo.(Cuerda) -> ()
como su segundo parámetro. En el cuerpo de la función, la función que pasamos se invoca con elmensaje
argumento.El ejemplo también ilustra cómo podemos invocar el
PrintMessage (_: con :)
función. losmi mensaje
constante se pasa como el primer argumento y laimprimir mensaje (_ :)
Funciona como el segundo argumento. Cuan genial es eso?Funciones como tipos de retorno
También es posible devolver una función desde una función. El siguiente ejemplo es un poco artificial, pero ilustra cómo se ve la sintaxis..
func compute (_ adición: Bool) -> (Int, Int) -> Int func add (_ a: Int, _ b: Int) -> Int return a + b func restra (_ a: Int, _ b: Int) -> Int return a - b si la adición return add else return restar deja computeFunction = compute (true) deja result = computeFunction (1, 2) print (result)los
calcular(_:)
La función acepta un booleano y devuelve una función de tipo.(Int, Int) -> Int
. loscalcular(_:)
La función contiene dos funciones anidadas que también son de tipo(Int, Int) -> Int
,añadir(_:_:)
ysustraer(_:_:)
.los
calcular(_:)
función devuelve una referencia a cualquiera de losañadir(_:_:)
o lasustraer(_:_:)
función, basada en el valor de laadición
parámetro.El ejemplo también muestra cómo usar el
calcular(_:)
función. Almacenamos una referencia a la función que es devuelta por elcalcular(_:)
función en elcomputeFunction
constante. Entonces invocamos la función almacenada encomputeFunction
, pasando en1
y2
, almacenar el resultado en elresultado
constante, e imprimir el valor deresultado
En la salida estándar. El ejemplo puede parecer complejo, pero en realidad es fácil de entender si sabes lo que está pasando.Conclusión
Ahora debe tener una buena comprensión de cómo funcionan las funciones en Swift y qué puede hacer con ellas. Las funciones son fundamentales para el lenguaje Swift, y las usarás ampliamente cuando trabajes con Swift.
En el siguiente artículo, nos sumergiremos primero en los cierres: una construcción poderosa que recuerda a los bloques en C y Objective-C, los cierres en JavaScript y las lambdas en Ruby.
Si desea aprender a usar Swift 3 para codificar aplicaciones del mundo real, consulte nuestro curso Crear aplicaciones de iOS con Swift 3. Ya sea que sea nuevo en el desarrollo de aplicaciones de iOS o desee cambiar de Objective-C, este El curso te ayudará a comenzar con Swift para el desarrollo de aplicaciones..