Swift необязательные параметры inout и nil

возможно ли иметь Optional функции в Swift? Я пытаюсь сделать это:

func testFunc( inout optionalParam: MyClass? ) {
    if optionalParam {
        ...
    }
}

...но когда я пытаюсь позвонить и пройти nil, это дает мне странные ошибки компиляции:

Type 'inout MyClass?' does not conform to protocol 'NilLiteralConvertible'

Я не понимаю, почему мой класс должен соответствовать какому-то специальному протоколу, когда он уже объявлен как необязательный.

5 ответов


он не будет компилироваться, потому что функция ожидает ссылку, но вы прошли nil. Проблема не имеет ничего общего с необязательным.

объявив параметр с inout означает, что вы присвоите ему некоторое значение внутри тела функции. Как он может присвоить значение nil?

вам нужно назвать это как

var a : MyClass? = nil
testFunc(&a) // value of a can be changed inside the function

если вы знаете C++ это C++ версии кода без дополнительных

struct MyClass {};    
void testFunc(MyClass &p) {}
int main () { testFunc(nullptr); }

и у вас есть эта ошибка сообщение

main.cpp:6:6: note: candidate function not viable: no known conversion from 'nullptr_t' to 'MyClass &' for 1st argument

, который является своего рода эквивалентом на тебя (но легче понять:)


это возможно, и это может иметь все, что связано с закрытие.()

необязательный может иметь значение nil, но он не ожидает nil. Таким образом, опция будет работать, если вы просто не передали ее функции или передали переменную типа MyClass? со значением nil. Как Брайан Стейтс.

когда вы пишете функцию, она должна иметь значение по умолчанию, чтобы быть необязательным параметром, например:

func testFunc(inout optionalParam:MyClass?={var nilRef:MyClass?;return &nilRef}()) {
    if optionalParam != nil {
        ...
    }
}

обратите внимание if optionalParam {...} изменяется if optionalParam != nil {...}

вы не можете uwwrap optionalParam не проверяя его, т. е.if optionalParam? != nil, как uwrapping, optionalParam? сбой при optionalParam==nil. ~Примечание, var a :MyClass? имеет значение nil, пока он не назначается.

звонок либо, testFunc(optionalParam:&a) или testFunc(), а не testFunc(nil)

думаю, вы можете получить две отдельные концепции, переплетенные, поскольку они имеют похожие имена, необязательные параметры и optionals. Optionals-это переменные с расширенным условием nil. Опционные параметры функция параметры, которые являются необязательными.

более дальнеишее чтение здесь. Apple пытается изменить глагол с необязательного параметра на "параметры со значениями по умолчанию". К сожалению, они не включили необязательное поведение параметров в эти новые необязательные вещи. Какой смысл передавать nil optionals как optionals, если они потерпят неудачу при разворачивании. Может быть, это становится глубже в основе того, что эта необязательная вещь, если ее можно передать перед разворачиванием... Кот Шредингера!--14-->


точный отрывок из документов - это:

вы можете передать только переменную в качестве аргумента для параметра in-out. Вы не можете передать константу или литеральное значение в качестве аргумента, потому что константы и литералы не могут быть изменены. Вы устанавливаете амперсанд (&) непосредственно перед именем переменной, когда вы передаете ее в качестве аргумента параметр inout, указывающий, что он может быть изменен функция.

обратите внимание, однако, что (отредактировано) в комментарии @gnasher вам нужно только передать класс как inout (aka по ссылке), Если вы намерены или хотите разрешить замену экземпляра другим экземпляром, а не просто изменить оригинал. Отрывок в документации, которая охватывает это:

In-Out Параметры

переменные параметры, как описано выше, могут быть изменены только в сама функция. Если вы хотите, чтобы функция изменяла параметр ценность и вы хотите, чтобы эти изменения сохранялись после вызова функции завершилось, вместо этого определите этот параметр как параметр in-out.

вот три теста, которые охватывают использование var и inout.

class Bar : Printable {
    var value = 1

    init(_ value:Int) { self.value = value }
    var description:String { return "Bar is: \(value)" }
}

let bar = Bar(1)
func changeBarWithoutInoutSinceBarIsAClassYaySwift(b:Bar) { b.value = 2 }
changeBarWithoutInoutSinceBarIsAClassYaySwift(bar)
println("after: \(bar)") // 2

var bar2 = Bar(0)
func tryToReplaceLocalBarWithoutInout(var b:Bar) { b = Bar(99) }
tryToReplaceLocalBarWithoutInout(bar2)
println("after: \(bar2)") // 0

var bar3 = Bar(0)
func replaceClassInstanceViaInout(inout b:Bar) { b = Bar(99) }
replaceClassInstanceViaInout(&bar3)
println("after: \(bar3)") // 99

на самом деле, что нужно @devios1, это "необязательный указатель". Но как inout класса MyClass? означает "указатель на необязательный". Следующее должно работать в Swift 4

class MyClass {
    // func foo() {}
}

func testFunc(_ optionalParam: UnsafeMutablePointer<MyClass>? ) {
    if let optionalParam = optionalParam {
        // optionalParam.pointee.foo()
        // optionalParam.pointee = MyClass()
    }
}

testFunc(nil)

var myClass = MyClass()
testFunc(&myClass)

это возможно, но вы должны заменить "inout" на "var"

Это работает только для Аргументов класса, а не для Struct. Объект класса передается как указатель, модификатор "inout" не нужен (и фактически ошибка). Атрибут 'var' должен быть добавлен, так как вы хотите изменить его значение внутри функции.