1. ホーム
  2. swift

[解決済み] Swift言語におけるエクスクラメーションマークの意味とは?

2022-02-15 21:14:07

質問内容

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言語の超初心者です。 ただ、基本を押さえようとしているところです。


UPDATE
私が見逃していたパズルの大きなピース(回答には直接書かれていない-少なくともこれを書いている時点では)は、次のようなときです。

var john: Person?

ということではありません。 john は、タイプ Person で、当初考えていたようにnil"になるかもしれません。単に私が誤解していたのは PersonPerson? は全く別の型です。 それを把握すると、他のすべての ? , ! の狂気、そして以下の素晴らしい回答で、より一層理解することができました。

解決方法は?

<ブロッククオート

インスタンスのアンラップとはどういう意味ですか?また、なぜそれが必要なのですか?

私が理解できる限りでは(私もこれは非常に新しいことです)...

この用語は、次のような意味を持っています。 Optional変数を光沢のある紙で包まれたプレゼントと考える。 .

Optional変数の値は、quot;wrap"されると、2つの値を持つenumになります(少しBooleanに似ています)。 この列挙型は、その変数が値を保持しているかどうかを記述します ( Some(T) ) か、そうでないか ( None ).

値がある場合は、変数をアンラップすることで取得できます(quot;unwrapping" を取得します)。 T から Some(T) ).

どのように john!.apartment = number73 とは異なり john.apartment = number73 ? (言い換え)

オプショナル変数の名前を書くと(例:テキスト john を使用せずに ! ) の場合、これは値そのもの (T) ではなく、 "wrapped" enum (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ケースを明示的に処理することを強制するので、(nilケースを処理することを忘れがちな)Obj-Cよりも安全性が向上しているのでしょう。

更新情報 :

感嘆符は、quot;Implicitly Unwrapped Optionals" を宣言する構文でも使用されています。

ここまでの例では john という変数が宣言されています。 var john:Person? であり、Optionalです。 その変数の実際の値が欲しい場合は、上記の3つの方法のいずれかを使って、アンラップする必要があります。

として宣言されている場合 var john:Person! この場合、変数は Implicitly Unwrapped Optional (Apple's book のこの見出しのセクションを参照) になります。 この種の変数は、値にアクセスする際にアンラップする必要はありません。 john は、追加の構文なしで使用できます。 しかし、Appleの本にはこう書いてある。

暗黙的にアンラップされたオプショナルは、後の時点で変数がnilになる可能性がある場合には使用しないでください。変数のライフタイム中に nil 値をチェックする必要がある場合は、常に通常のオプショナル型を使用してください。

アップデート2 :

記事の"です。 Swiftの面白い機能 Mike Ashは、オプショナル型について、いくつかの動機を述べています。 とても分かりやすい文章で素晴らしいと思います。

アップデート3 :

に関するもう一つの有用な記事です。 暗黙のうちにアンラップされるオプション はエクスクラメーションマークに使用します。 スウィフトとラストワンマイル クリス・アダムソン著。 この記事では、AppleがObjective-Cフレームワークで使用する型にnilを含む可能性があることを宣言するために使用する実用的な手段であると説明されている。 ある型をオプションとして宣言する(そのためには ? を使用)または暗黙のうちにアンラップされます。 ! は、安全性と利便性のトレードオフです。 この記事で紹介されている例では、Appleは型を暗黙的にアンラップすることを選択し、呼び出し側のコードをより便利にしましたが、安全性は低くなっています。

おそらくAppleは将来、自社のフレームワークを調べ上げ、暗黙のうちにアンラップされた("おそらく決してnil")パラメータの不確実性を取り除き、Objective-Cコードの正確な動作に基づいて、オプション("特定の(できれば文書で)状況で確かにnilとなり得る")または標準の非オプション("は決してnil")宣言でそれらを置き換えるかも知れません。