Domyślny opcjonalny parametr w funkcji Swift

109

Gdy ustawię wartość firstThingdomyślną, nilto zadziała, bez wartości domyślnej nilpojawia się błąd, że podczas wywoływania funkcji brakuje parametru.

Wpisując Int?, myślałem, że jest to opcjonalne z domyślną wartością nil, mam rację? A jeśli tak, dlaczego nie działa bez = nil?

func test(firstThing: Int? = nil) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}
test()
RickBrunstedt
źródło
1
Weź pod uwagę, że możesz napisać func test(firstThing: Int = 4): nie- Optionalparametr z wartością domyślną. OptionalTyp (czyli to, co ?w nazwie typu rozszerza się do) to typ wartości; „parametr opcjonalny” to niefortunna nazwa parametru, który może być obecny lub nie w wywołaniu funkcji, niezależnie od jego typu.
zneak
Jakiej wersji Swift używasz do testowania tego kodu? Twój kod działa dobrze !! Opcjonalne to tylko typ, a domyślne parametry działają dobrze, jak w przypadku innego typu w Swift
Victor Sigler

Odpowiedzi:

212

Opcje i parametry domyślne to dwie różne rzeczy.

Opcjonalna to zmienna, która może być nil, to wszystko.

Parametry domyślne używają wartości domyślnej, gdy pominiesz ten parametr, ta wartość domyślna jest określona w następujący sposób:func test(param: Int = 0)

Jeśli określisz parametr, który jest opcjonalny, musisz go podać, nawet jeśli wartość, którą chcesz przekazać, to nil. Jeśli twoja funkcja wygląda tak func test(param: Int?), nie możesz jej tak nazwać test(). Mimo że parametr jest opcjonalny, nie ma wartości domyślnej.

Można również połączyć dwa i mieć parametr, który pobiera opcjonalny gdzie niljest wartością domyślną, tak: func test(param: Int? = nil).

EmilioPelaez
źródło
30
„Jeśli określisz parametr, który jest opcjonalny, musisz go podać”. Świetnie, dzięki Swift
andrewtweber
8
@andrewtweber Doceniamy Twój humor, ale dla początkujących pomyślałem, że pomocne może być wyjaśnienie, że „Opcjonalne” odnosi się do dostarczenia obiektu lub wartości. Nie musisz tego robić, możesz zamiast tego podać nil (co oznacza brak obiektu lub wartości). Musisz tylko zdecydować, którą opcję wybierzesz.
JD Sandifer,
24

Argument domyślny umożliwia wywołanie funkcji bez przekazywania argumentu. Jeśli nie przekażesz argumentu, podawany jest argument domyślny. Więc używając twojego kodu, to ...

test()

... jest dokładnie taki sam jak ten:

test(nil)

Jeśli pominiesz domyślny argument, taki jak ten ...

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

... wtedy nie możesz już tego robić ...

test()

Jeśli to zrobisz, zostanie wyświetlony opisany błąd „brakujący argument”. Za każdym razem musisz przekazać argument, nawet jeśli ten argument to po prostu nil:

test(nil)   // this works
Aaron Rasmussen
źródło
19

Swift nie przypomina języków takich jak JavaScript, w których można wywołać funkcję bez przekazywania parametrów i nadal będzie ona wywoływana. Aby wywołać funkcję w Swift, musisz przypisać wartość do jej parametrów.

Wartości domyślne parametrów umożliwiają przypisanie wartości bez określania jej podczas wywoływania funkcji. Dlatego test()działa, gdy określisz wartość domyślną w deklaracji testu.

Jeśli nie to, że wartość domyślną, należy podać wartość na połączenia: test(nil).

Poza tym, i nie jest to bezpośrednio związane z tym pytaniem, ale prawdopodobnie warte odnotowania, używasz sposobu "C ++" do radzenia sobie z potencjalnie zerowymi wskaźnikami, aby radzić sobie z możliwymi zerowymi opcjami w Swift. Poniższy kod jest bezpieczniejszy (szczególnie w oprogramowaniu wielowątkowym) i pozwala uniknąć wymuszonego rozpakowywania opcjonalnego:

func test(firstThing: Int? = nil) {
    if let firstThing = firstThing {
        print(firstThing)
    }
    print("done")
}
test()
nbloqs
źródło
8

Mylisz się Optionalz domyślnym. An Optionalakceptuje wartość lub zero. Posiadanie wartości domyślnej pozwala na pominięcie argumentu podczas wywoływania funkcji. Argument może mieć wartość domyślną z Optionaltypem lub bez .

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

    print("param2 = \(param2)")

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

Przykładowe wywołania z wyjściem:

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

Podsumowując:

  • Wpisz z? (np. String?) to an Optionalmoże być nil lub może zawierać wystąpienie Type
  • Argument z wartością domyślną można pominąć w wywołaniu funkcji i zostanie użyta wartość domyślna
  • Jeśli oba Optionali mają wartość domyślną, to można je pominąć w wywołaniu funkcji LUB może być uwzględnione i może mieć wartość zerową (np. Param1: nil)
Chuck Krutsinger
źródło
czy mogę dodać domyślny parametr jako zmienną, taką jak let lub var? Dzięki
Yogesh Patel
@YogeshPatel Nie jestem pewien, co masz na myśli.
Chuck Krutsinger
jak var myName = "Yogesh". Teraz moja funkcja jest taka jak 1. func getFilterNames (name: string = myName) {} to podejście nie działa dla mnie. 2. func getFilterNames (name: string = "Yogesh") {} to podejście działa dla mnie. Ale chcę pierwszy, więc czy pomóż mi to osiągnąć. Wielkie dzięki!
Yogesh Patel
@YogeshPatel Myślę, że to, czego możesz chcieć func getFilterNames(name: inout String){ }, to zmiana przekazanej nazwy.
Chuck Krutsinger
Nie, nie, proszę pana. nie chcę modyfikować mojego parametru. Chcę tylko nadać domyślną wartość dla mojego parametru, ale nie tak jak statyczny „Yogesh”. Chcę zrobić tak, jak let name = "Yogesh" dynamiczna funkcja getFilterNames (name: string = name) w ten sposób. dostajesz to sir? Dzięki!
Yogesh Patel
4

w przypadku konieczności użycia parametru bool, wystarczy przypisać wartość domyślną.

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

wtedy możesz użyć bez lub z param:

test() //here flag automatically has the default value: false
test(WithFlag: true) //here flag has the value: true
Niib Fouda
źródło
Osoby, które to negatywnie oceniają, mogą zamiast tego naprawić niewłaściwą rzecz, aby inni zrozumieli.
Niib Fouda
3

„Parametr opcjonalny” oznacza „typ tego parametru jest opcjonalny”. Nie oznacza to: „Ten parametr jest opcjonalny i dlatego można go zignorować podczas wywoływania funkcji”.

Termin „parametr opcjonalny” wydaje się być mylący. Aby wyjaśnić, dokładniej jest powiedzieć „opcjonalny parametr typu” zamiast „opcjonalny parametr”, ponieważ słowo „opcjonalny” ma tutaj jedynie opisać typ wartości parametru i nic więcej.

Todanley
źródło
0

Jeśli chcesz móc wywołać parametr funcz lub bez parametru, możesz utworzyć sekundę funco tej samej nazwie, która wywołuje drugą.

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

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

teraz możesz wywołać funkcję o nazwie testbez lub bez parametru.

// both work
test()
test(firstThing: 5)
Sean256
źródło
Dlaczego miałbyś definiować dodatkową funkcję, skoro możesz po prostu określić nil jako wartość domyślną parametru?
Peter Schorn,
-1

Jest to trochę trudne, gdy próbujesz połączyć opcjonalny parametr i wartość domyślną tego parametru. Lubię to,

func test(param: Int? = nil)

Te dwa są zupełnie przeciwnymi pomysłami. Gdy masz opcjonalny parametr typu, ale podajesz również wartość domyślną, nie jest on już typem opcjonalnym, ponieważ ma wartość domyślną. Nawet jeśli wartością domyślną jest zero, swift po prostu usuwa opcjonalne powiązanie bez sprawdzania, jaka jest wartość domyślna.

Dlatego zawsze lepiej nie używać wartości nil jako wartości domyślnej.

Shubham Naik
źródło
1
To jest niepoprawne. Nie ma nic złego w opcjonalnej wartości domyślnej (parzystej nil).
Brian Kendig
mówię, że gdy zmienna ma wartość domyślną, nie jest opcjonalna w tym sensie, że zawsze będzie miała wartość.
Shubham Naik
1
To nieprawda i nie jestem pewien, co próbujesz opisać. Myślę, że słusznie mówisz, że gdy zmienna ma przypisaną wartość, zawsze zostanie ona przypisana; nie możesz cofnąć przypisania (ani nie chcesz), chyba że cofniesz przydział. A Swift poda błąd kompilacji, jeśli spróbujesz użyć zmiennej, zanim uzyska ona wartość (jak w var foo: String; print(foo)). Ale argument funkcji z wartością domyślną jest argumentem opcjonalnym (nie musisz go podawać w wywołaniu funkcji) i może być również typu Opcjonalnego (co pozwala nilna przypisanie go nawet jako wartość domyślna).
Brian Kendig,
Opcjonalny jest zasadniczo typem unii <Typ | Nil>, czyli może mieć określony typ lub typ zerowy. (Zakładając, że szybki miał Związki, czego nie robi, ale mówimy tutaj koncepcyjnie). tak Int? = zero jest w porządku.
Shayne,
-1

Wartość domyślna nie oznacza domyślnej wartości typu danych, tutaj wartość domyślna oznacza wartość zdefiniowaną w momencie definiowania funkcji. podczas definiowania zmiennej w funkcji musimy zadeklarować domyślną wartość zmiennej.

Mahesh Kulkarni
źródło