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()

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).


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

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()

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)

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.


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

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)

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.


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.