Parâmetro opcional padrão na função Swift

107

Quando eu definir firstThingcomo padrão, nilisso funcionará, sem o valor padrão de nil, recebo um erro informando que há um parâmetro ausente ao chamar a função.

Ao digitar Int?, pensei que era opcional com um valor padrão de nil, estou certo? E se sim, por que não funciona sem o = nil?

func test(firstThing: Int? = nil) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}
test()
RickBrunstedt
fonte
1
Considere que você pode escrever func test(firstThing: Int = 4): um não- Optionalparâmetro com um valor padrão. O Optionaltipo (que é o que ?em um nome de tipo se expande) é um tipo de valor; "parâmetro opcional" é um nome infeliz para um parâmetro que pode ou não estar presente em uma chamada de função, independentemente de seu tipo.
zneak de
Qual versão do Swift você usou para testar este código? Seu código funciona bem !! Opcional é apenas um tipo, e os parâmetros padrão funcionam bem como com outro tipo em Swift
Victor Sigler

Respostas:

210

Opcionais e parâmetros padrão são duas coisas diferentes.

Um opcional é uma variável que pode ser nil, é isso.

Os parâmetros padrão usam um valor padrão quando você omite esse parâmetro, este valor padrão é especificado assim:func test(param: Int = 0)

Se você especificar um parâmetro opcional, deverá fornecê-lo, mesmo que o valor que deseja passar seja nil. Se sua função for assim func test(param: Int?), você não poderá chamá-la assim test(). Embora o parâmetro seja opcional, ele não possui um valor padrão.

Você também pode combinar os dois e ter um parâmetro que leva um opcional que nilé o valor padrão, como este: func test(param: Int? = nil).

EmilioPelaez
fonte
27
"Se você especificar um parâmetro opcional, deverá fornecê-lo". Ótimo, obrigado Swift
andrewtweber
8
@andrewtweber Seu humor é apreciado, mas para iniciantes, achei que seria útil esclarecer que "Opcional" se refere a fornecer um objeto ou valor. Você não precisa fazer isso; em vez disso, você pode fornecer nil (que representa a ausência de um objeto ou valor). Você só precisa decidir qual opção está escolhendo.
JD Sandifer
23

O argumento padrão permite que você chame a função sem passar um argumento. Se você não passar o argumento, o argumento padrão será fornecido. Então, usando seu código, isso ...

test()

... é exatamente o mesmo que este:

test(nil)

Se você deixar o argumento padrão como este ...

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

... então você não pode mais fazer isso ...

test()

Se o fizer, obterá o erro "argumento ausente" que descreveu. Você deve passar um argumento todas as vezes, mesmo que esse argumento seja apenas nil:

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

Swift não é como linguagens como JavaScript, onde você pode chamar uma função sem passar os parâmetros e ela ainda será chamada. Portanto, para chamar uma função em Swift, você precisa atribuir um valor a seus parâmetros.

Os valores padrão dos parâmetros permitem que você atribua um valor sem especificá-lo ao chamar a função. É por isso que test()funciona quando você especifica um valor padrão na declaração do teste.

Se você não incluir esse valor padrão, você precisa fornecer o valor na chamada: test(nil).

Além disso, e não diretamente relacionado a esta questão, mas provavelmente vale a pena notar, você está usando a maneira "C ++" de lidar com ponteiros possivelmente nulos, para lidar com possíveis opcionais nulos em Swift. O código a seguir é mais seguro (especialmente em software multithreading) e permite que você evite o desembrulhamento forçado do opcional:

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

Você está confundindo Optionalcom um padrão. Um Optionalaceita um valor ou nulo. Ter um padrão permite que o argumento seja omitido na chamada da função. Um argumento pode ter um valor padrão com ou sem ser do Optionaltipo.

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

    print("param2 = \(param2)")

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

Chamadas de exemplo com saída:

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:

  • Digite com? (por exemplo, String?) é um Optionalpode ser nulo ou pode conter uma instância de Tipo
  • O argumento com o valor padrão pode ser omitido de uma chamada para a função e o valor padrão será usado
  • Se Optionale tiver o padrão, ele pode ser omitido da chamada de função OU pode ser incluído e pode ser fornecido com um valor nulo (por exemplo, param1: nulo)
Chuck Krutsinger
fonte
posso adicionar o parâmetro padrão como uma variável, como let ou var? Obrigado
Yogesh Patel
@YogeshPatel Não tenho certeza do que você quer dizer.
Chuck Krutsinger
como var myName = "Yogesh". Agora, minha função é como 1. func getFilterNames (name: string = myName) {} esta abordagem não está funcionando para mim. 2. func getFilterNames (name: string = "Yogesh") {} esta abordagem está funcionando para mim. Mas eu quero o primeiro, então você pode me ajudar a conseguir isso. Muito obrigado!
Yogesh Patel
@YogeshPatel Acho que o que você pode querer é func getFilterNames(name: inout String){ }que você modifique o nome que foi passado.
Chuck Krutsinger
Não, não senhor. eu não quero modificar meu parâmetro. Eu só quero dar o valor padrão ao meu parâmetro, mas não como "Yogesh" estático. Eu quero fazer como let name = "Yogesh" dynamic func getFilterNames (name: string = name) assim. recebendo este senhor? Obrigado!
Yogesh Patel
3

"Parâmetro opcional" significa "o tipo deste parâmetro é opcional". Isso não significa "Este parâmetro é opcional e, portanto, pode ser ignorado ao chamar a função".

O termo "parâmetro opcional" parece confuso. Para esclarecer, é mais preciso dizer "parâmetro de tipo opcional" em vez de "parâmetro opcional", pois a palavra "opcional" aqui se destina apenas a descrever o tipo de valor do parâmetro e nada mais.

Todanley
fonte
3

caso você precise usar um parâmetro bool, basta atribuir o valor padrão.

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

então você pode usar sem ou com o parâmetro:

test() //here flag automatically has the default value: false
test(WithFlag: true) //here flag has the value: true
Niib Fouda
fonte
Para as pessoas que votam contra isso, você pode consertar a coisa errada, para que os outros entendam.
Niib Fouda,
0

Se você quiser chamar o funccom ou sem o parâmetro, você pode criar um segundo funccom o mesmo nome que chama o outro.

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

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

agora você pode chamar uma função chamada testsem ou sem o parâmetro.

// both work
test()
test(firstThing: 5)
Sean256
fonte
Por que você definiria uma função adicional quando poderia apenas especificar nil como o valor padrão para o parâmetro?
Peter Schorn
-1

É um pouco complicado quando você tenta combinar parâmetro opcional e valor padrão para esse parâmetro. Como isso,

func test(param: Int? = nil)

Esses dois são ideias completamente opostas. Quando você tem um parâmetro de tipo opcional, mas também fornece um valor padrão para ele, ele não é mais um tipo opcional, pois tem um valor padrão. Mesmo se o padrão for nulo, o swift simplesmente remove a ligação opcional sem verificar qual é o valor padrão.

Portanto, é sempre melhor não usar nil como valor padrão.

Shubham Naik
fonte
1
Isso está incorreto. Não há nada de errado em um opcional ter um valor padrão (par nil).
Brian Kendig
o que estou dizendo é que, uma vez que uma variável tem um valor padrão, ela não é opcional no sentido de que sempre terá um valor.
Shubham Naik
1
Isso não é verdade, e não tenho certeza do que você está tentando descrever. Acho que você está dizendo corretamente que, uma vez que uma variável tenha um valor atribuído a ela, ela sempre será atribuída; você não pode desatribuí-lo (nem gostaria), a menos que desaloque-o. E o Swift apresentará um erro de compilação se você tentar usar uma variável antes que ela tenha um valor (como em var foo: String; print(foo)). Mas um argumento de função com um valor padrão é um argumento opcional (você não precisa passá-lo na chamada de função) e também pode ser do tipo Opcional (permitindo nilser atribuído a ele, mesmo como o valor padrão).
Brian Kendig
Um opcional é essencialmente um tipo de união de <Tipo | Nil>, ou seja, pode ter o tipo especificado ou o tipo nulo. (Supondo que a swift tivesse sindicatos, o que não é verdade, mas estamos falando conceitualmente aqui). tão Int? = nil está perfeitamente bem.
Shayne
-1

O valor padrão não significa o valor padrão do tipo de dados. Aqui, o valor padrão significa o valor definido no momento da definição da função. temos que declarar o valor padrão da variável enquanto definimos a variável na função.

Mahesh Kulkarni
fonte