ProgrammingiOS開発者

Swiftにおける構造体(struct)の動作はどのようなもので、ストレージと動作の観点からクラス(class)と何が違うのか、そしてなぜ構造体はデータモデリングにおいてより一般的に使用されるのか?

Hintsage AIアシスタントで面接を突破

答え。

質問の背景

Swiftは初めから値型、すなわちデータモデリングの主要手段として構造体(struct)に重点を置いています。Objective-Cではすべてがオブジェクト(クラス)でしたが、Swiftは単純なモデル、データ、小規模なビジネスオブジェクトに対して構造体の使用を奨励します。

問題

多くの開発者、特に他のオブジェクト指向言語の経験がある人々は、すべてにクラスを使用してしまう誤解をしています。これはメモリの問題(参照サイクル)、オブジェクトを渡した際の予期しない変更、スレッドの安全性の問題を引き起こします。クラスは参照型だからです。

解決策

Swiftでは構造体は値型であり、代入や関数への渡しの際にコピーされますが、クラス(参照型)は参照を渡します。これが、複雑なライフサイクルや継承のロジックがないモデルには構造体が好まれる理由です。

コードの例:

struct Point { var x: Int var y: Int } var p1 = Point(x: 10, y: 20) var p2 = p1 p2.x = 30 // p1.xは10のままです

主な特徴:

  • 構造体のコピーは常に値のコピーを引き起こします(値のセマンティクス)
  • メモリリークの可能性が低い
  • 継承をサポートせず、プロトコルのみをサポート

トリック的な質問。

構造体には継承者(サブクラス)を持てますか?

いいえ、Swiftの構造体は継承をサポートしていません。全ての振る舞いの拡張はプロトコルとエクステンションを通じてのみ可能です。

構造体は関数に渡す際に常にコピーされるということですか?

実際には、Swiftはコピーオンライト最適化を使用します。構造体を変更しない限り、それはコピーされず、変更時にのみコピーが作成されます。これは標準コレクションや複雑な構造体に関わります。

var arr1 = [1, 2, 3] var arr2 = arr1 arr2.append(4) // ここでのみコピーが発生します

どのような場合に構造体を使用できないのか?

  • アイデンティティが必要な場合(オブジェクト性、参照による比較)
  • 継承者が必要な場合
  • 唯一のインスタンス(シングルトン)が必要な場合

一般的な誤りとアンチパターン

  • 単純なモデルやデータ構造にクラスを使用すること
  • 構造内に参照型を保持し、それをコピーしようとすること
  • 構造体を「参照によって」渡すことを期待し、構造体を通じて外部オブジェクトを変更しようとすること

実生活の例

ネガティブケース

同種のデータを保持するためにクラスを使用した結果、メモリへの頻繁なアクセスによるパフォーマンスの低下、複雑なメモリ管理、参照の混乱に関するバグが発生しました。

長所:

  • AnyObjectとして配列に格納することができる

短所:

  • パフォーマンスが低下
  • スレッドの安全性に関する問題
  • メモリ管理の問題

ポジティブケース

データモデルに対して構造体を使用し、安全にコピーされ、リークがなく、余分な複雑さがないこと。

長所:

  • コピーの簡便さと安全性
  • 参照サイクルがない
  • テストが容易

短所:

  • 継承を必要とするパターンを実装できない
  • 構造体内に参照型がある場合、コピーや変更時に驚きが発生する可能性がある