変数 - swift[] 意味




Swift言語で感嘆符の意味は何ですか? (15)

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?

それは私がもともと思っていたように、「 johnPerson型のものであり、それはゼロかもしれません」という意味ではありません。 私はそのPersonPerson?単に誤解していましたPerson? 完全に別のタイプです。 一度私はそれを把握し、他のすべての?! 狂気、そして以下の大きな答えはもっと意味がありました。


「インスタンスをアンラップする」とはどういう意味ですか? それはなぜ必要なのですか?

限り、私は(これは私にも非常に新しいですが)動作することができます...

"ラップされた"という言葉は、Optional変数を現在のように考えるべきであることを意味します

"wrapped"の場合、Optional変数の値は、2つの値(ブール値のような)を持つ列挙型です。 この列挙型は、変数が値( Some(T) )を保持するか、保持しない( None )かを示します。

値がある場合、これは変数をアンラップすることによって得られます( Some(T)からTを得る)。

john!.apartment = number73とはどのようなものですか?。 john.apartment = number73john.apartment = number73ますか? (言い換え)

Optional変数の名前を書いた場合( !なしのtext johnなど)、これは値自体(T)ではなく、 "ラップされた"列挙型(Some / None)を指します。 したがって、 johnPersonインスタンスではなく、 apartmentメンバーはいません。

john.apartment
// 'Person?' does not have a member named 'apartment'

実際のPerson値は、さまざまな方法でアンラップできます。

  • "強制アンラッピング": john! (存在する場合はPerson値を与え、nilの場合は実行時エラーを返す)
  • "optional binding": if let p = john { println(p) }ならば(値が存在すればprintln実行する)
  • "optional chaining": john?.learnAboutSwift() (値が存在する場合、この作成されたメソッドを実行します)

私はあなたがノーケースで何が起こるべきか、そしてどれくらいそうであるかに応じて、これらの方法をアンラップする方法を選択すると思います。 この言語設計は、明示的にnilのケースを処理するよう強制します。Obj-Cよりも安全性が向上すると思います(nilの場合を処理するのを忘れるのは簡単です)。

更新

感嘆符は、「暗黙的にアンラップされたオプション」を宣言する構文でも使用されます。

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

それがvar john:Person! 代わりに、変数は暗黙的にアンラップされたオプションです(Appleの本のこの見出しのセクションを参照してください)。 値にアクセスするときにこの種の変数をラップする必要はなく、追加構文なしでjohnを使用できます。 しかし、Appleの本によれば、

後で変数がゼロになる可能性がある場合、暗黙的にアンラップされたオプションは使用しないでください。 変数の存続期間中にnil値をチェックする必要がある場合は、通常のオプションの型を常に使用してください。

アップデート2

Mike Ashの記事 " Interesting Swift Features "には、オプションのタイプの動機付けがあります。 私はそれが偉大な、明確な執筆だと思う。

アップデート3

感嘆符のための暗黙のうちにアンラップされたオプションの使用に関する別の有益な記事:Chris Adamsonの " Swift and the Last Mile " この記事では、これはAppleがObjective-Cフレームワークで使用される型を宣言するために使用した実用的な方法であり、これにはnilが含まれている可能性があると説明されています。 タイプをオプション( ?を使用)または暗黙的にアンラップ( !を使用)として宣言するのは、 "安全性と利便性の間のトレードオフ"です。 この記事で与えられた例では、Appleは暗黙のうちにラップされていない型を宣言して、呼び出しコードをより便利にしましたが、安全性は低くしました。

おそらく、Appleは、暗黙のうちにアンラップされた(おそらく決して無関係な)パラメータの不確定性を取り除き、オプション(「確かにはうまくいけば、文書化された状況ではないだろう」) Objective-Cコードの正確な振る舞いに基づいて、-optional( "is not nil")宣言を実行します。


C言語から来たのであれば、 "メモリアドレス0(NULL)であるかもしれないタイプXのオブジェクトへのポインタ"を考えています。動的に型指定された言語から来ているなら、考えている "おそらくタイプXのオブジェクトですが、未定義のタイプかもしれません"。 これらのどちらも実際には正しいものではありませんが、ラウンドアバウトの方法で最初のものが近くにあります。

あなたがそれを考えなければならない方法は、それが次のような目的であるかのようです:

struct Optional<T> {
   var isNil:Boolean
   var realObject:T
}

オプションの値をfoo == nilでテストしているときは、本当にfoo.isNil返していますfoo! foo.isNil == falseというアサーションでfoo.isNil == falsefoo.isNil == falsefooを実行するときにfoo実際にはnilであるため、これを注意することが重要foo! これはランタイムエラーです。したがって、値が無限にならないことが確実でない限り、通常は条件付きletを使用することをお勧めします。 このようなトリッキーなことは、値がどこにもない場合には、テストすることを強いられずに言語を厳密に型指定できることを意味します。

実際には、コンパイラによって処理が行われるため、実際には動作しません。 高レベルにFoo?型がありFoo? これはFooとは別のものであり、 Foo型を受け入れる関数がnil値を受け取ることを防ぎますが、低レベルでは、プロパティーやメソッドがないため、オプションの値は真のオブジェクトではありません。 実際には、力をアンラップするときに適切なテストでNULL(0)を指すポインタである可能性があります。

感嘆符が型にあることがわかる他の状況があります:

func foo(bar: String!) {
    print(bar)
}

これは、強制アンラップでオプションを受け入れることとほぼ同じです。つまり、

func foo(bar: String?) {
    print(bar!)
}

これを使用して、技術的にオプションの値を受け入れるメソッドを持つことはできますが、nilの場合は実行時エラーが発生します。 Swiftの現在のバージョンでは、これは明らかにis-not-nilアサーションをバイパスしているので、代わりに低レベルのエラーが発生します。 一般的には良い考えではありませんが、別の言語のコードを変換する場合には便利です。


TL; DR

Swift言語で感嘆符の意味は何ですか?

感嘆符は効果的にこう言っています。「私は、このオプションは間違いなく価値があることを知っています。 それを使用してください。 "これはオプションの値の強制アンラッピングと呼ばれます。

let possibleString: String? = "An optional string."
print(possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."

let assumedString: String! = "An implicitly unwrapped optional string."
print(assumedString)  // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."

出典: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_399 : https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_399


johnがオプションのvar(このように宣言されている)

var john: Person?

johnが値を持たない(ObjCの場合、nilの値で)可能性があります。

感嘆符は、基本的にコンパイラに「これは価値があることを知っているので、テストする必要はありません」と伝えます。 あなたがそれを使いたくないなら、それを条件付きでテストすることができます:

if let otherPerson = john {
    otherPerson.apartment = number73
}

この内部は、johnが値を持っているかどうかだけ評価されます。


! オブジェクトの終わりにオブジェクトがオプションであり、そうでなければ無限を返すことができる場合はアンラップすると言います。 これは、しばしばプログラムをクラッシュさせるエラーをトラップするためによく使用されます。


johnはオプションのvarです。 したがって、 nil値を含むことができます。 値がnilでないことを確認するには、a ! var名の最後に。

ドキュメントから

オプションに値が含まれていることが確認できたら、オプションの名前の末尾に感嘆符(!)を追加して、その基本値にアクセスできます。 感嘆符は効果的にこう言っています。「私は、このオプションは間違いなく価値があることを知っています。 それを使用してください。

0以外の値をチェックするもう1つの方法は

    if let j = json {
        // do something with j
    }

自問してみてください

  • タイプperson? apartmentメンバー/プロパティがありますか? または
  • タイプのpersonapartmentメンバー/プロパティを持っていますか?

この質問に答えることができない場合は、

理解するためには、 ジェネリックスの超基礎レベルの理解が必要な場合があります。 here参照してhere Swiftの多くのものはGenericsを使って書かれています。 オプションが含まれています

以下のコードはこのStanfordのビデオから入手できます。 最初の5分間を強くお勧めします

Optionalは列挙型で、2つしかない

enum Optional<T>{
    case None
    case Some(T)
}

let x: String? = nil //actually means:

let x = Optional<String>.None
let x :String? = "hello" //actually means:

let x = Optional<String>.Some("hello")
var y = x! // actually means:

switch x {
case .Some(let value): y = value
case .None: // Raise an exception
}

オプションのバインディング:

let x:String? = something
if let y = x {
    // do something with y
}
//Actually means:

switch x{
case .Some(let y): print)(y) // or whatever else you like using 
case .None: break
}

あなたはvar john: Person?と言うときvar john: Person? あなたは実際にそのような意味です:

enum Optional<Person>{
case .None
case .Some(Person)
}

上記のenumにはapartmentというプロパティがありapartmentか? あなたはどこにでもそれを見ますか? それはまったくありません ! しかし、あなたがそれをアンラップする場合、つまりperson!行うperson! あなたがすることができます...ボンネットの下で行うことは: Optional<Person>.Some(Person(name: "John Appleseed"))

var john: Person代わりにvar john: Personを定義していたのですvar john: Person? あなたはもはや必要がなくなります! Person自体にはapartmentメンバーがいるので

なぜ使用するのかについての今後の議論として! このQ&Aを見る


あなたがC#に精通しているなら、これは疑問符を使って宣言されたNullable型のようなものです:

Person? thisPerson;

この場合の感嘆符は、次のようにnull可能型の.Valueプロパティにアクセスするのと同じです。

thisPerson.Value

この場合...

var John:Person!

それは、当初、ジョンは価値がないことを意味し、それは設定され、いったん設定されてしまうと決して元に戻りません。 したがって、便宜上、オプションのvarにアクセスするための簡単な構文を使用できます。これは、 "暗黙のうちにアンラップされたオプション"


オプションとして使用すると、オプションがアンラップされ、何かがある場合に表示されます。 もしあなたがif-else文でそれを使用するならば、NOTはNOTのためのコードです。 例えば、

if (myNumber != 3){
 // if myNumber is NOT 3 do whatever is inside these brackets.
)

ストーリー全体はオプションのバールと呼ばれる迅速な機能から始まります。 これらは値を持つか、値を持たない値である。 一般的にswiftでは、初期化されていない変数を使用することはできません。これは、クラッシュや予期しない理由が発生したり、バックドアのプレースホルダをサーバーにする可能性があります。 したがって、最初に値が決定されていない変数を宣言するには、 '?'を使用します。 そのような変数が宣言されている場合、それを一部の式の一部として使用するには、それらをアンラップしてから使用する必要があります。アンラッピングとは、変数の値がオブジェクトに適用されることを検出する操作です。 それらを使用しようとするとアンラップしないと、コンパイル時にエラーが発生します。 オプションのvarである変数をアンラップするには、感嘆符 "!" 使用されている。

このようなオプションの変数には、たとえばシステムや独自のプログラムによって値が割り当てられることがありますが、そのような状況では、疑問符「?」を使用してオプションの変数を宣言するのではなく、UIアウトレットのような場合があります。 を使用しております "!"。

したがって、システムは、 "!"で宣言されているこの変数は、 現在はオプションであり、価値はありませんが、その生涯の後半で値を受け取ります。

したがって、感嘆符には2つの異なる用途があります。1.オプションとなる変数を宣言し、後に値を確実に受け取るようにします。2.オプションの変数を式で使用する前にアンラップします。

上記の説明はあまり技術的なものを避けています。


他の有用であるがより詳細な中心的な答えに追加する大きな画像の視点:

Swiftでは、感嘆符はいくつかの文脈で現れます:

  • let name = nameLabel!.textlet name = nameLabel!.text
  • 暗黙のうちにvar logo: UIImageView!されていないオプション: var logo: UIImageView!
  • 強制鋳造: logo.image = thing as! UIImage logo.image = thing as! UIImage
  • 未処理の例外: try! NSJSONSerialization.JSONObjectWithData(data, []) try! NSJSONSerialization.JSONObjectWithData(data, [])

これらはそれぞれ異なる意味を持つ異なる言語構造ですが、3つの共通のものがあります。

1.感嘆符は、Swiftのコンパイル時の安全チェックを回避します。

あなたが使うとき! Swiftでは本質的に言っています。「コンパイラー、ここでエラー起こると思うのは分かっていますが、決してそれは決してできないと確信しています。

それはすべての有効なコードがSwiftのコンパイル時型システムのボックスに収まるわけではありません。 エラーが発生しないことを論理的に証明できる状況がありますが、コンパイラにそれ証明することはできません。 Swiftのデザイナーがこれらの機能を最初に追加した理由です。

しかし、あなたが使うたびに! あなたは、エラーの回復パスを持っていることを排除しています。つまり、そのことを意味します...

2.感嘆符は潜在的なクラッシュです。

感嘆符はまた、「ちょっとスイフト、私はそれが私のために回復パスをコード化するよりもあなたが私のアプリ全体クラッシュさせる方が良いというこのエラーは決して起こり得ないと確信しています。

それは危険な主張です。 これは正しいものです:ミッションクリティカルなコードでは、あなたのコードの不変量に​​ついて懸命に考えていますが、偽の出力はクラッシュよりも悪いかもしれません。

しかし、私が見るとき! 野生では、それほど慎重に使用されることはほとんどありません。 代わりに、あまりにも多くの場合、「この値はオプションであり、 なぜそれが無かったり、その状況を適切に処理するかについてあまりにも難しくないと思っていませんでした! それはコンパイルされたので...私のコードは正しいですよね? "

感嘆符の傲慢に注意してください。 代わりに...

3.感嘆符は控えめに使用することをお勧めします。

これらのすべて! 構成は? あなたがエラー/無しの場合に対処するように強制する相手:

  • 条件付きアンラッピング: if let name = nameLabel?.text { ... }
  • オプション: var logo: UIImageView?
  • 条件付きキャスト: logo.image = thing as? UIImage logo.image = thing as? UIImage
  • Nil-on-failureの例外: try? NSJSONSerialization.JSONObjectWithData(data, []) try? NSJSONSerialization.JSONObjectWithData(data, [])

あなたが使うように誘惑されたら! なぜ、あなたが使用していないのかを慎重に考えてみるのは良いこと? 代わりに。 もしあなたが本当にあなたのプログラムをクラッシュさせるのは最高のオプションです! 操作は失敗しますか? なぜその値はオプション/有効であるのですか?

あなたのコードがnil / errorの場合に取ることができる妥当なリカバリパスはありますか? そうなら、それをコード化します。

コンパイラがそのことを知っているように、ロジックが再作成されるという合理的な方法はありますか? もしそうなら、それを行います。 コードのエラーが起こりにくくなります。

エラーを処理するための合理的な方法がなく、エラーを無視して間違ったデータを処理するという合理的な方法がない場合、クラッシュするよりも悪い場合があります。 それらは力のアンラッピングを使う時間です。

私は定期的に自分のコードベース全体を検索し! そのすべての使用を監査します。 非常に少数の使用法が精査に立ち向かう。 (この記事の執筆時点では、Siestaフレームワーク全体にはちょうどtwo instancesがあります。)

それはあなたが決して使うべきでないと言っているわけではありませ ! あなたのコードでは、 念頭に置いて、それをデフォルトのオプションにしないでください。


短く(!):変数を宣言した後、変数が値を保持していることを確認した後。

let assumedString: String! = "Some message..."
let implicitString: String = assumedString

そうでなければ、価値を渡した後に毎回これを行う必要があります...

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark

私は違いがあると思います:

var john: Person?

ヨーンを意味することはできません

john?.apartment = number73

コンパイラはこの行を次のように解釈します。

if john != nil {
    john.apartment = number73
}

john!.apartment = number73

コンパイラはこの行を単純に次のように解釈します。

john.apartment = number73

したがって、! if文をunwrapしてより速く実行させますが、johnがnilであれば、実行時エラーが発生します。

ここでラップすると、ラップされたメモリであるとは限りませんが、コードラップされていることを意味します。この場合、ifステートメントでラップされます。また、Appleは実行時にパフォーマンスに細心の注意を払います。最高のパフォーマンスでアプリを稼働させることができます。

更新:

4年後にこの回答に戻ると、私はでそれから最高の評判を得ました:)私はその時にラッピングの意味を少し誤解しました。 4年後、私はここでアンラッピングの意味は、元のコンパクトなフォームからコードを拡張することだと考えています。 また、そのオブジェクトの周りの曖昧さを取り除くことを意味します。私たちは、その定義によってわからないので、それはゼロではありません。 上のアシュリーの答えと同じように、それを何も含まれていないプレゼントと考えてください。 しかし、私はまだアンラップがコードのアンラッピングではなく、メモリベースのアンラッピングではなくenumを使用していると考えています。


Simple the Optional variable allows nil to be stored.

var str : String? = nil

str = "Data"

To convert Optional to the Specific DataType, We unwrap the variable using the keyword "!"

func get(message : String){
   return
}

get(message : str!)  // Unwapped to pass as String






forced-unwrapping