web-dev-qa-db-ja.com

Swiftのオプションの配列と空の配列

私はSwiftに次のような単純なPersonクラスがあります:

class Person {
    var name = "John Doe"
    var age = 18
    var children = [Person]?

    \\ init function goes here, but does not initialize children array
}

childrenをオプションの配列として宣言する代わりに、次のように宣言して空の配列として初期化するだけです。

var children = [Person]()

私はどちらのアプローチがより良いかを決定しようとしています。配列をオプションの配列として宣言すると、メモリをまったく使用しなくなりますが、空の配列には少なくともある程度のメモリが割り当てられますか?したがって、オプションの配列を使用すると、少なくともある程度のメモリが節約されます。私の最初の質問は次のとおりだと思います:実際にメモリの節約が実際に行われているのですか、それとも私の想定が間違っているのでしょうか。

一方、それがオプションの場合、それを使用しようとするたびに、オブジェクトを追加または削除する前に、それがnilかどうかを確認する必要があります。したがって、そこには効率のいくらかの損失があります(しかし、私は想像しますが、それほどではありません)。

私はオプションのアプローチが好きです。すべてのPersonに子供がいるわけではないので、childrenが定住して家族を養うことを決定するまで、nilPersonにしないでください。

とにかく、どちらか一方のアプローチに他の特定の利点または欠点があるかどうかを知りたいです。それは何度も何度も出てくるデザインの問題です。

35
Aaron Rasmussen

空の配列またはオプションのいずれかを選択する機能により、セマンティックの観点からデータをより適切に説明する配列を適用できます。

私は選択します:

  • リストが空の場合は空の配列ですが、一時的な状態であり、最終的には少なくとも1つの要素が必要です。オプションではないことは、配列が空であってはならないことを明確にします
  • コンテナーエンティティのライフサイクル全体でリストを空にできる場合は、オプションです。オプションであることは、配列が空であることを明確にします

いくつか例を挙げましょう。

  • マスターと詳細を含む注文書(製品ごとに1つの詳細):注文書には0の詳細を含めることができますが、これは一時的なステータスです。0製品の注文書を作成しても意味がないためです。
  • 子供を持つ人:人は生涯子供を持つことはできません。これは一時的な状態ではありませんが(永続的ではありません)、オプションを使用すると、子供がいないことは正当なことです。

私の意見は、コードをより明確で自明にすることのみに関するものであることに注意してください。どちらのオプションを選択しても、パフォーマンス、メモリ使用量などに関して、大きな違いはないと思います。

16
Antonio

私はヨルディから反対のケースを作るつもりです-「この人には子供がいません」と明確に言うのと同じように空の配列は、あなたに面倒のトンを節約します。 children.isEmptyは、子供の存在を簡単に確認できるため、予期しないnilを解いたり心配したりする必要はありません。

また、メモとして、何かをオプションとして宣言することは、スペースがゼロになることを意味しません。これは、.NoneOptional<Array<Person>>の場合です。

20
Nate Cook

興味深いことに、私たちは最近、この非常に同じ問題について職場でほとんど議論していません。

微妙な意味の違いがあることを示唆する人もいます。例えば。 nilは、子供がいないことを意味しますが、0はどういう意味ですか?それは「子供がいる、それらの0全体」を意味しますか?私が言ったように、純粋なセマンティクス "0の子を持っている"および "子を持たない"このモデルをコードで操作する場合、違いはありません。その場合は、もっと簡単でガードレスなアプローチを選ばないのはなぜですか?

nilを保持することを示唆する人もいます。たとえば、バックエンドからモデルを取得するときに、何かがうまくいかず、子ではなくエラーが発生したことを示している可能性があります。しかし、私はモデルがこのタイプのセマンティクスを持たないようにし、nilを過去のエラーの指標として使用しないでください。

私は個人的に、モデルは可能な限りダムである必要があり、この場合のdumbestオプションは空の配列です。

オプションがあると、その?を最後までドラッグして、guard letif let、または??を繰り返し使用できます。

NSCoding実装には追加のアンラップロジックが必要です。モデルをビューコントローラーに表示するときは、単純なperson.children?.count ?? 0ではなくperson.children.countを実行する必要があります。

これらすべての操作の最終目標は、UIに何かを表示することです。本当に言いますか

nilの「この人には子供がいません」と「この人には子供がいない」と空の配列は対応していますか?私はあなたがそうしないことを望みます:)

最後のわら

最後に、これは本当に私が持っている最も強い議論です

Cocoaフレームワークには、 UIViewController :: childViewControllers などの例がたくさんあります。

純粋なSwift world: Dictionary :: keys からでも、これは少し遠いかもしれませんが。

人がnilの子を持つことはできても、SKNodeはできないのはなぜですか?私にとっては、類推は完璧です。ねえ、SKNodeのメソッド名もchildrenです:)

私の見解:これらの配列を本当に良いもののようにオプションとして保持する明らかな理由があるはずです。そうでなければ、空の配列は同じセマンティクスを提供し、アンラップを少なくします。

最後のわら

最後に、非常に良い記事へのいくつかの参照、それらのそれぞれ

Natashaの投稿には、NSHipsterのブログ投稿への リンクがありSwiftificationの段落には、この:

たとえば、NSArrayの戻り値をnull可能としてマークする代わりに、多くのAPIは空の配列を返すように変更されています。つまり、これらは同じ値(つまり、何もない)ですが、オプションではない配列の方がはるかに簡単に処理できます。

14
i4niac

時々、存在しないものと空であることに違いがあります。

ユーザーが電話番号のリストを変更できるアプリがあり、その変更をmodifiedPhoneNumberListとして保存するとします。変更が発生していない場合、配列はnilになります。ユーザーが解析済みの数値を削除して変更した場合、すべての配列は空になります。

空は既存の電話番号をすべて削除することを意味し、nilは既存の電話番号をすべて保持することを意味します。違いはここで重要です。

プロパティが空であるか存在しないかを区別できない場合、または空であるかどうかが問題ではない場合は、次の方法に進みます。 Personが唯一の子を失う場合、countが1であるかどうかを確認するのではなく、その子を削除して空の配列を作成するだけで、配列全体をnilに設定する必要があります。

5
Declan McKenna

私はいつも空の配列を使います。

私の控えめな意見では、Swiftでのオプションの最も重要な目的は、nilの可能性があるいくつかの値を安全にラップすることです。配列はすでにこのタイプのラッパーとして機能しています-配列を確認できます内部に何かがあり、forループやマッピングなどでその値に安全にアクセスします。ラッパー内にラッパーを配置する必要がありますか?そうは思いません。

3
Trev14

Swiftはオプションの値とオプションのアンラップを利用するように設計されています。

couldは、配列をnilとして宣言します。これにより、非常に小さな(ほとんど気づかない)量のメモリが節約されます。 。

Swiftのデザインパターンを満足させるために、nil値を表す配列の代わりにオプションの配列を使用します:)

私も思います

if let children = children {

}

よりもよさそうだ:

if(children != nil){

}
1
Yordi