ProgrammingiOS開発者

Swiftにおける値型と参照型の違いを説明してください。各々を使用するべき時はいつですか?

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

回答。

Swiftには二つの基本的なデータ型があります:値型(value types)と参照型(reference types)。

  • 値型(Value types)。 構造体(struct)、列挙型(enum)、および基本的な型(IntDoubleBoolなど)が含まれます。値を渡したり代入したりするとき、値はコピーされるため、コピーの変更は元のものには影響しません。
  • 参照型(Reference types)。 これはクラス(class)およびそれに関連する型です。渡されたものはオブジェクト自体ではなく、オブジェクトへの参照ですので、一つの参照を通じた変更は他の参照からも見えるようになります。

使用するタイミング:

  • データが独立したコピーであることを望む場合は、値型を使用してください(例:CGPointCGSize、状態を共有してはならないモデルなど)。
  • オブジェクト間で状態を共有する必要がある場合は、参照型が適しています(例:マネージャー、コントローラー、サービスなど)。

例:

struct Point { var x: Int var y: Int } class Person { var name: String init(name: String) { self.name = name } } var p1 = Point(x: 0, y: 0) var p2 = p1 p2.x = 10 // p1.xは0のまま var person1 = Person(name: "Alex") var person2 = person1 person2.name = "Sam" // person1.nameも"Sam"になる

トリックの質問。

letを使った構造体とクラスの違いは何ですか? letで作成されたclassのインスタンスは完全に不変ですか?

回答:

値型(struct)に対しては、letがオブジェクトとそのプロパティを不変にします。

参照型(class)に対しては、letが参照を再割り当てすることを禁止しますが、オブジェクトのプロパティは保護されません。それらは、クラス内でletとして声明されていない限り変更可能です。

例:

class Box { var value: Int init(value: Int) { self.value = value } } let box = Box(value: 10) box.value = 20 // OK! // box = Box(value: 30) // エラー:boxを再割り当てできません

このテーマに関する無知から生じた実際のエラーの例。


物語

支払いアプリケーションではトランザクションモデルをクラスとして定義しましたが、状態は存在しないはずでした。バグが発生しました:トランザクションリストの同時操作中に異なる画面のデータが予測不可能に編集されました。各コンポーネントが独自のコピーで作業するようにモデルを構造体へ移行することに決定しました。


物語

プロジェクトではユーザー設定をクラスに保存し、値は渡すことでコピーされると思っていました。データを変更すると、一つの画面が意図せず他の画面に影響を与えました。なぜなら、両方とも同じオブジェクトへの参照で作業していたからです。


物語

シリアル化モジュールではモデルデータを参照型として宣言したため、どんな変更もキャッシュの状態を破壊していました。値型に置き換えた後、問題は解決されました:データは各操作で独立するようになりました。