1. ホーム
  2. swift

[解決済み] なぜクラスではなくストラクチャーを選ぶのか?

2022-03-19 22:14:12

質問

Swiftで遊んでいて、Javaのバックグラウンドを持っているのですが、なぜクラスではなく、ストラクチャーを選びたいのでしょうか? それらは同じもののように思えますが、構造体はより少ない機能を提供しています。 なぜそれを選ぶのですか?

解決方法は?

大人気のWWDC2015の講演「Protocol Oriented Programming in Swift」によると、( ビデオ , トランスクリプト ) 、Swift は、多くの状況でクラスよりも構造体をより良くする多くの機能を提供します。

構造体は、比較的小さくてコピー可能なものが望ましいです。クラスで起こるように同じインスタンスへの複数の参照を持つよりも、コピーの方がずっと安全だからです。これは、多くのクラスやマルチスレッド環境で変数を受け渡しする場合に特に重要です。常に変数のコピーを他の場所に送ることができれば、他の場所があなたの下で変数の値を変更することを心配する必要はありません。

構造体を使用すると、メモリリークや複数のスレッドが1つの変数のインスタンスにアクセスしたり変更したりする際の競争を心配する必要が大幅に減ります。(ただし、クロージャ内で構造体をキャプチャする場合は例外で、明示的にコピーするようにマークしない限り、実際にはインスタンスへの参照をキャプチャすることになるからです)。

また、クラスは1つのスーパークラスからしか継承できないので、クラスが肥大化することもあります。そのため、緩やかな関係しかない多くの異なる能力を包含する巨大なスーパークラスを作成することが推奨されます。プロトコルを使うことで、特にプロトコルに実装を提供できるプロトコル拡張では、この種の動作を実現するためにクラスを必要としなくなります。

この講演では、クラスが好ましいとされるこれらのシナリオを整理しています。

<ブロッククオート
  • インスタンスのコピーや比較は意味がない(例:Window)
  • インスタンスの寿命が外部効果と結びついている(例:TemporaryFile)
  • インスタンスは単なるシンクであり、外部の状態(例:CGContext)への書き込み専用のコンジットである。

構造体がデフォルトで、クラスはフォールバックであるべきだということを暗に示しています。

一方 プログラミング言語「Swift のドキュメントは、やや矛盾しています。

<ブロッククオート

構造体のインスタンスは常に値で渡され、クラスのインスタンスは常に値で渡されます。 インスタンスは常に参照渡しです。これは、両者が というように、異なる種類のタスクに適しています。データ プロジェクトに必要な構造および機能を決定します。 各データ構造をクラスとして定義するのか、それとも 構造体

一般的なガイドラインとして、1つ以上の場合、構造体を作成することを検討してください。 のいずれかに該当する。

  • 構造体の主な目的は、いくつかの比較的単純なデータ値をカプセル化することです。
  • の代入や受け渡しの際に、カプセル化された値は参照されるのではなく、コピーされると考えるのが妥当でしょう。 のインスタンスを作成します。
  • 構造体に格納されるプロパティは、それ自体が値型であり、これも参照ではなく複写されることが予想される。
  • 構造体は、他の既存の型からプロパティや動作を継承する必要はない。

構造体の良い候補の例としては、以下のようなものがあります。

  • 幾何学的な形状の大きさ。おそらく、widthプロパティとheightプロパティ(両方ともDouble型)をカプセル化したもの。
  • シリーズ内の範囲を参照する方法。おそらくstartプロパティとlengthプロパティがカプセル化されており、両方ともInt型である。
  • 3D座標系における点。おそらく、x、y、zのプロパティをカプセル化し、それぞれをDouble型とする。

それ以外の場合は、クラスを定義し、そのクラスのインスタンスを作成します。 を管理し、参照渡しする。実際のところ、これは ほとんどのカスタムデータ構造は、構造体ではなく、クラスであるべきです。

ここでは、デフォルトでクラスを使用し、特定の状況でのみ構造体を使用すべきであると主張しています。最終的には、値型と参照型の実世界での意味を理解した上で、構造体やクラスを使用するタイミングについて、十分な情報を得た上で判断する必要があります。また、これらの概念は常に進化しており、Swift Programming Languageのドキュメントは、プロトコル指向プログラミングの講演が行われる前に書かれたものであることを心に留めておいてください。