Parámetro opcional predeterminado en la función Swift

107

Cuando establezco el firstThingvalor predeterminado, nilesto funcionará, sin el valor predeterminado de nil, obtengo un error de que falta un parámetro al llamar a la función.

Al escribir Int?, pensé que lo hacía opcional con un valor predeterminado de nil, ¿estoy en lo cierto? Y si es así, ¿por qué no funciona sin el = nil?

func test(firstThing: Int? = nil) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}
test()
RickBrunstedt
fuente
1
Considere que puede escribir func test(firstThing: Int = 4): un no Optionalparámetro con un valor predeterminado. El Optionaltipo (que es lo que ?en un nombre de tipo se expande) es un tipo de valor; "parámetro opcional" es un nombre desafortunado para un parámetro que puede estar presente o no en una llamada de función, independientemente de su tipo.
zneak
¿Qué versión de Swift ha utilizado para probar este código? ¡Tu código funciona bien! Los opcionales son solo un tipo, y los parámetros predeterminados funcionan bien como con otro tipo en Swift
Victor Sigler

Respuestas:

210

Los parámetros opcionales y predeterminados son dos cosas diferentes.

Un Opcional es una variable que puede ser nil, eso es todo.

Los parámetros predeterminados usan un valor predeterminado cuando omite ese parámetro, este valor predeterminado se especifica así:func test(param: Int = 0)

Si especifica un parámetro que es opcional, debe proporcionarlo, incluso si el valor que desea pasar es nil. Si su función se ve así func test(param: Int?), no puede llamarla así test(). Aunque el parámetro es opcional, no tiene un valor predeterminado.

También se pueden combinar los dos y tener un parámetro que tiene una opción donde niles el valor por defecto, como esto: func test(param: Int? = nil).

EmilioPelaez
fuente
27
"Si especifica un parámetro que es opcional, debe proporcionarlo". Genial, gracias Swift
andrewtweber
8
@andrewtweber Se agradece su humor, pero para los novatos, pensé que podría ser útil aclarar que "Opcional" se refiere a proporcionar un objeto o valor. No tiene que hacer eso, puede proporcionar nil (que representa la ausencia de un objeto o valor) en su lugar. Solo tienes que decidir qué opción estás eligiendo.
JD Sandifer
23

El argumento predeterminado le permite llamar a la función sin pasar un argumento. Si no pasa el argumento, se proporciona el argumento predeterminado. Entonces, usando tu código, esto ...

test()

... es exactamente lo mismo que esto:

test(nil)

Si omite el argumento predeterminado como este ...

func test(firstThing: Int?) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}

... entonces ya no podrás hacer esto ...

test()

Si lo hace, obtendrá el error "argumento faltante" que describió. Debe pasar un argumento cada vez, incluso si ese argumento es solo nil:

test(nil)   // this works
Aaron Rasmussen
fuente
18

Swift no es como lenguajes como JavaScript, donde puede llamar a una función sin pasar los parámetros y aún se llamará. Entonces, para llamar a una función en Swift, debe asignar un valor a sus parámetros.

Los valores predeterminados para los parámetros le permiten asignar un valor sin especificarlo al llamar a la función. Es por eso que test()funciona cuando especifica un valor predeterminado en la declaración de prueba.

Si no se incluye ese valor por defecto, es necesario proporcionar el valor de la llamada: test(nil).

Además, y no está directamente relacionado con esta pregunta, pero probablemente valga la pena señalarlo, está utilizando la forma "C ++" de tratar con punteros posiblemente nulos, para tratar con posibles opcionales nulos en Swift. El siguiente código es más seguro (especialmente en software de subprocesos múltiples) y le permite evitar el desenvolvimiento forzado del opcional:

func test(firstThing: Int? = nil) {
    if let firstThing = firstThing {
        print(firstThing)
    }
    print("done")
}
test()
nbloqs
fuente
7

Estás confundiendo Optionalcon tener un valor predeterminado. An Optionalacepta un valor o nulo. Tener un valor predeterminado permite omitir el argumento al llamar a la función. Un argumento puede tener un valor predeterminado con o sin ser de Optionaltipo.

func someFunc(param1: String?,
          param2: String = "default value",
          param3: String? = "also has default value") {
    print("param1 = \(param1)")

    print("param2 = \(param2)")

    print("param3 = \(param3)")
}

Ejemplo de llamadas con salida:

someFunc(param1: nil, param2: "specific value", param3: "also specific value")

param1 = nil
param2 = specific value
param3 = Optional("also specific value")

someFunc(param1: "has a value")

param1 = Optional("has a value")
param2 = default value
param3 = Optional("also has default value")

someFunc(param1: nil, param3: nil)

param1 = nil
param2 = default value
param3 = nil

Para resumir:

  • Escriba con? (por ejemplo, ¿String?) es un Optionalpuede ser nulo o puede contener una instancia de Type
  • El argumento con el valor predeterminado se puede omitir de una llamada a la función y se utilizará el valor predeterminado
  • Si ambos Optionaly tienen el valor predeterminado, entonces se puede omitir de la llamada a la función O se puede incluir y se le puede proporcionar un valor nulo (por ejemplo, param1: nil)
Chuck Krutsinger
fuente
¿Puedo agregar un parámetro predeterminado como una variable como let o var? Gracias
Yogesh Patel
@YogeshPatel No estoy seguro de lo que quieres decir.
Chuck Krutsinger
como var myName = "Yogesh". Ahora, mi función es como 1. func getFilterNames (name: string = myName) {} este enfoque no me funciona. 2. func getFilterNames (name: string = "Yogesh") {} este enfoque me está funcionando. Pero quiero el primero, así que, ¿pueden ayudarme a lograrlo? ¡Muchas gracias!
Yogesh Patel
@YogeshPatel Creo que lo que puede querer es lo func getFilterNames(name: inout String){ }que le permitirá modificar el nombre que se pasó.
Chuck Krutsinger
No no señor. no quiero modificar mi parámetro. Solo quiero dar un valor predeterminado a mi parámetro pero no como "Yogesh" estático. quiero hacer como let name = "Yogesh" función dinámica getFilterNames (nombre: cadena = nombre) así. conseguir esto señor? ¡Gracias!
Yogesh Patel
4

en caso de que necesite usar un parámetro bool, solo necesita asignar el valor predeterminado.

func test(WithFlag flag: Bool = false){.....}

entonces puedes usar sin o con el parámetro:

test() //here flag automatically has the default value: false
test(WithFlag: true) //here flag has the value: true
Niib Fouda
fuente
Para las personas que votan negativamente por esto, puedes arreglar lo incorrecto para que otros lo entiendan.
Niib Fouda
3

"Parámetro opcional" significa "el tipo de este parámetro es opcional". No significa "Este parámetro es opcional y, por lo tanto, puede ignorarse al llamar a la función".

El término "parámetro opcional" parece confuso. Para aclarar, es más exacto decir "parámetro de tipo opcional" en lugar de "parámetro opcional", ya que la palabra "opcional" aquí solo pretende describir el tipo de valor de parámetro y nada más.

Todanley
fuente
0

Si desea poder llamar al funccon o sin el parámetro, puede crear un segundo con funcel mismo nombre que llame al otro.

func test(firstThing: Int?) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}

func test() {
    test(firstThing: nil)
}

ahora puede llamar a una función nombrada testsin o sin el parámetro.

// both work
test()
test(firstThing: 5)
Sean256
fuente
¿Por qué definiría una función adicional cuando podría especificar nil como valor predeterminado para el parámetro?
Peter Schorn
-1

Es un poco complicado cuando intenta combinar un parámetro opcional y un valor predeterminado para ese parámetro. Me gusta esto,

func test(param: Int? = nil)

Estas dos son ideas completamente opuestas. Cuando tiene un parámetro de tipo opcional pero también le proporciona un valor predeterminado, ya no es un tipo opcional ya que tiene un valor predeterminado. Incluso si el valor predeterminado es nil, swift simplemente elimina el enlace opcional sin verificar cuál es el valor predeterminado.

Por tanto, siempre es mejor no utilizar nil como valor predeterminado.

Shubham Naik
fuente
1
Esto es incorrecto. No hay nada de malo en que un opcional tenga un valor predeterminado (par nil).
Brian Kendig
lo que estoy diciendo es que una vez que una variable tiene un valor predeterminado, no es opcional en el sentido de que siempre tendrá un valor.
Shubham Naik
1
Eso no es cierto y no estoy seguro de lo que está tratando de describir. Creo que está diciendo correctamente que una vez que se le asigna un valor a una variable, siempre se le asignará; no puede desasignarlo (ni desearía hacerlo) a menos que lo desasigne. Y Swift le dará un error de compilación si intenta usar una variable antes de que tenga un valor (como en var foo: String; print(foo)). Pero un argumento de función con un valor predeterminado es un argumento opcional (no tiene que pasarlo en la llamada a la función) y también puede ser de tipo Opcional (permitiendo nilque se le asigne, incluso como valor predeterminado).
Brian Kendig
Un opcional es esencialmente un tipo de unión de <Tipo | Nil>, es decir, puede tener el tipo Especificado o el Tipo Nil. (Suponiendo que Swift tuviera sindicatos, lo cual no es así, pero estamos hablando conceptualmente aquí). tan Int? = nil está perfectamente bien.
Shayne
-1

El valor predeterminado no significa el valor predeterminado del tipo de datos. Aquí el valor predeterminado es el valor medio definido en el momento de definir la función. tenemos que declarar el valor predeterminado de la variable al definir la variable en función.

Mahesh Kulkarni
fuente