Swiftの関数にOptional
inout
パラメーターを指定することは可能ですか?私はこれをやろうとしています:
func testFunc( inout optionalParam: MyClass? ) {
if optionalParam {
...
}
}
...しかし、それを呼び出してnil
を渡そうとすると、奇妙なコンパイルエラーが発生します。
Type 'inout MyClass?' does not conform to protocol 'NilLiteralConvertible'
クラスがすでにオプションとして宣言されているのに、なぜクラスが特別なプロトコルに準拠する必要があるのかわかりません。
関数は参照を期待しているが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
これは、あなたが得たものと同等です(しかし理解しやすい)
実際、@ devios1に必要なのは「オプションのポインタ」です。しかし、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)
正確な ドキュメントからのパス は次のとおりです。
変数は、入出力パラメーターの引数としてのみ渡すことができます。定数とリテラルは変更できないため、定数またはリテラル値を引数として渡すことはできません。アンパーサンド(&)を変数として引数に入力パラメーターとして渡す場合、変数名の直前に配置して、関数で変更できることを示します。
ただし、@ gnasherのコメントに従って(編集済み)、クラスをinout(別名参照)として渡す必要があるのは、インスタンスを別のインスタンスに置き換えたり、インスタンスを置き換えたりするだけでなく、オリジナルが変更されました。これをカバーするドキュメンテーションの節は次のとおりです:
入出力パラメーター
上記の変数パラメーターは、関数内でのみ変更できます。関数でパラメーターの値を変更し、関数呼び出しの終了後もそれらの変更を保持する場合は、代わりにそのパラメーターを入出力パラメーターとして定義します。
Varとinoutの使用法をカバーする3つのテストを次に示します。
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