Swiftプログラミング言語ガイド次の例があります。
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { println("\(name) is being deinitialized") }
}
class Apartment {
let number: Int
init(number: Int) { self.number = number }
var tenant: Person?
deinit { println("Apartment #\(number) is being deinitialized") }
}
var john: Person?
var number73: Apartment?
john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)
//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)
次に、アパートを人に割り当てるときに、感嘆符を使用して「インスタンスをアンラップ」します。
john!.apartment = number73
「インスタンスをアンラップする」とはどういう意味ですか? なぜ必要なのですか? 単に次の操作を実行することとどう違うのですか?
john.apartment = number73
私は Swift 言語を初めて使いました。基礎を理解しようとしています。
更新:
私が見逃していたパズルの大きなピース (回答には直接記載されていません - 少なくともこの記事を書いている時点では) は、次の操作を行うときです。
var john: Person?
これは、私が最初に考えていたように、「john
は 型でありPerson
、nil である可能性がある」という意味ではありません。私は単に、 とPerson
が完全に別の型であると誤解していましたPerson?
。それを理解すると、他のすべての?
、!
狂気、および以下の優れた回答がはるかに理解しやすくなりました。
ベストアンサー1
「インスタンスをアンラップする」とはどういう意味ですか? なぜ必要なのですか?
私が理解できる限りでは(これも私にとって非常に新しいことですが)...
「ラップされた」という用語は、Optional 変数を光沢のある紙で包まれたプレゼントと考える必要があることを意味します。プレゼントは (残念ながら!) 空である可能性があります。
「ラップ」されている場合、Optional 変数の値は、2 つの値を持つ列挙型 (ブール値に少し似ています) になります。この列挙型は、変数が値を保持するか ( Some(T)
)、保持しないか ( None
) を表します。
値がある場合は、変数を「アンラップ」する(T
から を取得するSome(T)
)ことによって取得できます。
は とどう
john!.apartment = number73
違うのですかjohn.apartment = number73
?(言い換え)
Optional 変数の名前 ( なしの text などjohn
)を記述すると!
、これは値自体 (T) ではなく、「ラップされた」列挙型 (Some/None) を参照します。したがって、john
は のインスタンスではなくPerson
、メンバーを持ちませんapartment
。
john.apartment
// 'Person?' does not have a member named 'apartment'
実際のPerson
値はさまざまな方法でアンラップできます。
- 「強制アンラップ」:
john!
(Person
値が存在する場合は値を返します。値が nil の場合は実行時エラーになります) - 「オプションのバインディング」:
if let p = john { println(p) }
(println
値が存在する場合に実行します) - 「オプションの連鎖」:
john?.learnAboutSwift()
(値が存在する場合はこの作成されたメソッドを実行します)
nil の場合に何が起こるか、そしてそれが起こる可能性がどの程度かに応じて、これらのアンラップ方法のいずれかを選択することになると思います。この言語設計では、nil の場合を明示的に処理するように強制されるため、Obj-C (nil の場合の処理を忘れやすい) よりも安全性が向上すると考えられます。
アップデート:
感嘆符は、「暗黙的にアンラップされた Optionals」を宣言するための構文でも使用されます。
これまでの例では、john
変数は として宣言されておりvar john:Person?
、これは Optional です。その変数の実際の値が必要な場合は、上記の 3 つの方法のいずれかを使用して、変数をアンラップする必要があります。
代わりにとして宣言された場合var john:Person!
、変数は暗黙的にアンラップされた Optional になります (Apple の書籍でこの見出しのセクションを参照してください)。値にアクセスするときにこの種の変数をアンラップする必要はなく、john
追加の構文なしで使用できます。ただし、Apple の書籍では次のように述べられています。
暗黙的にアンラップされたオプションは、後で変数が nil になる可能性がある場合は使用しないでください。変数の有効期間中に nil 値をチェックする必要がある場合は、常に通常のオプション型を使用してください。
アップデート2 :
記事 "興味深いSwiftの機能Mike Ash による「」は、optional 型に対する動機付けを示しています。わかりやすく素晴らしい文章だと思います。
アップデート3 :
感嘆符の暗黙的にアンラップされたオプションの使用に関する別の役立つ記事: "Swift とラストマイルChris Adamson による「Apple の Objective-C フレームワークで使用される型を宣言するための実用的な手段であり、nil が含まれる可能性がある」という記事で説明されています。型をオプションとして宣言する ( を使用?
) か、暗黙的にラップ解除する ( を使用!
) かは、「安全性と利便性のトレードオフ」です。記事で示されている例では、Apple は型を暗黙的にラップ解除することを選択しており、呼び出しコードはより便利になりますが、安全性は低下します。
おそらく Apple は将来的にフレームワークを精査し、暗黙的にアンラップされた (「おそらく nil になることはない」) パラメータの不確実性を排除し、Objective-C コードの正確な動作に基づいて、オプションの (「特定の状況 (できれば文書化されているとよいのですが) 状況では確かに nil になる可能性がある」) または標準の非オプションの (「nil になることはない」) 宣言に置き換えるかもしれません。