3

オプションの連鎖は、常にオプションの値を返します。

オプションの連鎖を nil 値で呼び出すことができるという事実を反映するために、オプションの連鎖呼び出しの結果は、クエリしているプロパティ、メソッド、または添え字が非オプションの値を返す場合でも、常にオプションの値になります。

Swift プログラミング言語

遊び場でタイプがオプションではないのはなぜですか?

let stringOptEmpty: String? = ""
stringOptEmpty?.isEmpty // is true
stringOptEmpty?.isEmpty.dynamicType // Bool.Type

しかし、次のコードは

let isOk = stringOptEmpty?.isEmpty.dynamicType
isOk.dynamicType // Optional<Bool.Type>.Type
4

1 に答える 1

4

TLDR;

プレイグラウンド サイドバー/列は、変数(ミュータブル/イミュータブル) に割り当てられた値であろうと、割り当てられていない「自由浮動」の値であろうと、プレイグラウンドの式を動的に解決します。

最初の例はvaluedynamicTypeに適用され、その特定の値の型( : )に解決されます。true.dynamicTypeBool.Type

一方、2番目の例は、具体的な型を持たなければならない変数(不変ですが、ここでは変数を使用してvalueとは異なる)に適用dynamicTypeされるため、任意の種類を保持できる型に解決されます変数が実際に保持している値に関係なく、ラップされた値 (または) と(ここでは、具体的には) です。したがって、 は2 番目の例で解決されます。truefalsenilnilOptional<Bool.Type>.NonedynamicTypeOptional<Bool.Type>.Type


詳細

プレイグラウンドのサイドバー/列に表示される値は、通常、次の表示規則に従います。

  • 割り当て式の場合、サイドバーに表示される値は割り当てられた値です。

    var a = 4 // shows '4'
    a = 2     // shows '2'
    let b: () = (a = 3)
              /* shows '()': the _value_ assigned to 'b', which is the _result_
                 of the assignment 'a = 3', to which a _side effect_ is that 'a'
                 is assigned the value '3'. */
    
  • 代入を含まない式の場合、サイドバーに表示される値は通常、式の結果です。

    true          // shows 'true'
    1 > 3         // shows 'false'
    let c = 3
    c             // shows '3'
    c.dynamicType // shows 'Int.Type'
    

最初の例 (2 ~ 3 行目) では、割り当てがなく、プレイグラウンドは式の値(/result) を動的に解決してからdynamicType、その値を解決します。オプションを扱っているため、は単純にラップされた型 (この場合はtrue) の値であるか、型固有 .Noneの値です。プレイグラウンドがたとえばサイドバーにlet a: Int? = nilasの結果を表示したとしてnilも、表示される値は実際には同じではありません.None( nil)let b: String = nil

  • の場合let a: Int? = nil、 のa実際にはOptional<Int.Type>.None
  • 一方let b: String? = nil、のbOptional<String.Type>.None

これを念頭に置いて、解決されdynamicTypeた非nil が具体的なラップされた型になるのは当然です(あなたの例でBool.Typeは、当然、の型ですtrue)が、解決されdynamicTypenil値には一般的なオプションとラップされた型情報の両方が含まれます.

struct Foo {
    let bar: Bool = true
}

var foo: Foo? = Foo()

/* .Some<T> case (non-nil) */
foo?.bar             // true <-- _expression_ resolves to (results in) the _value_ 'true'
foo?.bar.dynamicType // Bool.Type <-- dynamic type of the _result of expression_
true.dynamicType     // Bool.Type <-- compare with this

/* .None case (nil) */
foo = nil
foo?.bar.dynamicType // nil <-- _expression_ resolves to the _value_ 'Optional<Foo.Type>.None'
Optional<Foo.Type>.None.dynamicType
                     // Optional<Foo.Type>.Type <-- compare with this

ここで、値を変数に代入する場合、当然、変数には具象型が必要です。実行時に割り当てる値はまたは のいずれ.None.Some<T>になるため、変数の型はこれら両方のケースの値を保持できる型でなければなりません(変数が値を保持するか非値Optional<T.Type>を保持するかは無視します)。これは、2 番目の例で示したケースです:変数の(ここでは不変ですが、 variable を使用しvalueとは 異なります)は、変数の実際の値が何であれ、との両方を保持できる型です。 、したがってこの型に解決されます。.nilnildynamicTypeisOk.None.Some<T>dynamicTypeOptional<Bool.Type>.Type


括弧で式をラップすると、Swift Playground のランタイム イントロスペクションが回避されますか?

興味深いことに、 を適用する前に式が括弧で囲まれている場合、Playground.dynamicTypeサイドバーは、実際の値が不明であるかのように.dynamicType、ラップされた式を式の型として解決します。たとえば、(...)in(...).dynamicTypeは、実行時に解決される値ではなく、具体的な型を持つ変数として扱われます。

/* .Some case (non-nil) */
foo?.bar               // true
(foo?.bar).dynamicType /* Optional<Bool>.Type <-- as if (...) 
                          is a _variable_ of unknown value         */

/* .None case (nil) */
foo = nil
(foo?.bar).dynamicType /* Optional<Bool>.Type <-- as if (...) 
                          is a _variable_ of unknown value         */

さらに、プレイグラウンドで括弧で囲まれた単独の式は、(サイドバーで) 何にも解決されないことに注意してください。式を括弧で囲むと、sidebar:s のランタイム イントロスペクションを回避するかのようになります (これは、括弧dynamicTypeで囲まれた式が、プレイグラウンドがこれらの式のランタイム情報を使用できないかのように解決される理由を説明します)。

var a = 4 // shows '4'
(a = 2)   // shows nothing; can't expand or get details in sidebar

これがなぜなのかは説明できませんが、Swift プレイグラウンドの特殊性として分類します。

于 2016-05-28T11:23:27.013 に答える