クラスよりも構造体を選ぶ理由 質問する

クラスよりも構造体を選ぶ理由 質問する

Java のバックグラウンドから Swift をいじってみると、なぜ Class ではなく Struct を選択するのでしょうか。どちらも同じもののように思えますが、Struct の方が機能が少ないようです。では、なぜそれを選択するのでしょうか。

ベストアンサー1

非常に人気のあったWWDC 2015の講演「Swiftでのプロトコル指向プログラミング」(ビデオトランスクリプト)、Swift には、多くの状況でクラスよりも構造体の方が優れているいくつかの機能が用意されています。

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

構造体を使用すると、メモリ リークや、変数の 1 つのインスタンスにアクセスしたり変更したりするために複数のスレッドが競合することについて心配する必要がはるかに少なくなります。(より技術的な考え方を持つ人のために説明すると、例外はクロージャ内で構造体をキャプチャする場合です。これは、明示的にコピー対象としてマークしない限り、実際にはインスタンスへの参照をキャプチャするためです)。

クラスは単一のスーパークラスからしか継承できないため、クラスが肥大化してしまうこともあります。そのため、ゆるやかにしか関連していないさまざまな機能を網羅する巨大なスーパークラスを作成する傾向があります。プロトコルを使用すると、特にプロトコルに実装を提供できるプロトコル拡張機能を使用すると、クラスでこのような動作を実現する必要がなくなります。

講演では、クラスが好まれる次のようなシナリオが説明されています。

  • インスタンスのコピーや比較は意味がありません(例Window:)
  • インスタンスの有効期間は外部効果に結びついています(例TemporaryFile:)
  • インスタンスは単なる「シンク」であり、外部状態への書き込み専用の導管です(例CGContext:)

これは、構造体がデフォルトであり、クラスがフォールバックであるべきであることを意味します。

一方で、Swift プログラミング言語ドキュメントには多少矛盾があります:

構造体インスタンスは常に値で渡され、クラス インスタンスは常に参照で渡されます。つまり、これらはさまざまな種類のタスクに適しています。プロジェクトに必要なデータ構造と機能を検討する際には、各データ構造をクラスとして定義するか、構造体として定義するかを決定します。

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

  • この構造の主な目的は、比較的単純なデータ値をいくつかカプセル化することです。
  • その構造体のインスタンスを割り当てたり渡したりするときに、カプセル化された値が参照されるのではなくコピーされると考えるのが妥当です。
  • 構造体によって格納されるプロパティはそれ自体が値型であり、参照されるのではなくコピーされることが予想されます。
  • 構造体は、別の既存の型からプロパティや動作を継承する必要はありません。

構造の適切な候補の例は次のとおりです。

  • 幾何学的図形のサイズ。おそらく、幅プロパティと高さプロパティ(両方とも Double 型)をカプセル化します。
  • シリーズ内の範囲を参照する方法。おそらく、両方とも Int 型の開始プロパティと長さプロパティをカプセル化します。
  • 3D 座標系内の点。それぞれ Double 型の x、y、z プロパティをカプセル化している可能性があります。

それ以外の場合は、クラスを定義し、そのクラスのインスタンスを作成し、参照によって管理および渡します。実際には、ほとんどのカスタム データ構造は構造体ではなくクラスである必要があります。

ここでは、クラスをデフォルトで使用し、構造体は特定の状況でのみ使用すべきであると主張しています。最終的には、値型と参照型の実際の意味を理解し、構造体とクラスをいつ使用するかについて情報に基づいた決定を下す必要があります。また、これらの概念は常に進化しており、Swift プログラミング言語のドキュメントはプロトコル指向プログラミングの講演が行われる前に作成されたことにも留意してください。

おすすめ記事