Swiftで開発していると、誰もが一度は手を止める瞬間に出会います。
「これはclassにするべき? それともstruct?」
私もSwiftを学び始めた頃は、なんとなくこの2つを選んでいました。奇妙なバグに遭遇して初めて、違いをきちんと勉強したのです。
まず結論からお話しします。
特別な理由がなければ、まず構造体(struct)を選びましょう。
クラスを使うのは、「共有される1つの状態」が本当に必要なときだけです。
Appleの公式ガイドラインも同じ考え方です。今日はその理由を順に説明します。
まず押さえたいポイント(3つ)
忙しい方のために、先にまとめます。
- 構造体は値型です。コピーすると完全に別の値になります。
- クラスは参照型です。コピーしても同じインスタンスを指します。
- 迷ったらまずはstruct、継承や共有状態が必要なときだけclassです。
この3行だけ覚えておけば、半分は終わりです。
値型と参照型は何が違う?
言葉だけでは分かりにくいですよね。コードで見るのが一番早い方法です。
まずは構造体です。コピーした瞬間、それぞれ独立した存在になります。
struct Point { var x = 0 }
var a = Point()
var b = a // 値がコピーされた
b.x = 10
print(a.x, b.x)
// 出力: 0 10
bを変更しても、aはそのままです。それぞれが自分の値を持っているからです。
次はクラスです。同じようなコードに見えますが、結果は異なります。
class Box { var x = 0 }
let a = Box()
let b = a // 参照がコピーされた(同じオブジェクト)
b.x = 10
print(a.x, b.x)
// 出力: 10 10
bだけを変更したのに、aまで10になりました。
2つが同じインスタンスを指しているからです。私を悩ませたバグは、まさにこれでした。
では、いつ何を使う?(選択基準)
実務で判断するとき、私はこの表を頭に思い浮かべます。
| 状況 | 判断 |
|---|---|
| 単純にデータを保持するモデル | 構造体 |
| コピー後も互いに独立していてほしい | 構造体 |
| 継承が必須 | クラス |
| 複数の場所で同じインスタンスを共有 | クラス |
| Objective-Cとの連携が必要 | クラス |
もう少し具体的に整理すると、次のようになります。
- 座標、色、サイズのように値そのものを表すなら、構造体が自然です。
- 画面コントローラやネットワークマネージャのように、1つの状態を複数箇所で共有して見る必要があるなら、クラスが適しています。
- AppleのSwiftUIがViewをstructにしているのも同じ理由です。軽量で予測しやすいからです。
ちなみにSwift標準ライブラリのArray、String、Dictionaryはすべて構造体です。それほど値型が基本だということです。
構造体を先に勧める理由
値型は予測しやすいものです。
渡した値が別の場所でこっそり変更される心配がありません。関数に渡しても、元の値は安全です。
マルチスレッド環境でも安心です。共有状態がないため、データ競合が減るからです。
一方、クラスは強力ですが慎重さが必要です。同じインスタンスをあちこちで保持すると、どこで値が変わったのか追跡しにくくなります。
だから「基本はstruct、必要なときだけclass」という習慣が、バグを大きく減らしてくれます。
いつ使い、いつ避けるべきか
最後に、判断基準を短くまとめます。
- 構造体を使う:データ中心のモデル、独立したコピーが必要な場合、スレッドセーフが重要な場合
- クラスを使う:継承が必要な場合、1つのインスタンスを共有する場合、識別子(identity)に意味がある場合
- 避ける:単純なモデルに慣習でclassを使うこと、共有が必要なのにstructで無理に代用すること
面接ではこう聞かれます
Q. 構造体とクラスの最大の違いは何ですか?
構造体は値型、クラスは参照型です。構造体はコピーすると完全に独立した値になりますが、クラスはコピーしても同じインスタンスを指します。また、継承とdeinitを使えるのはクラスだけです。
Q. Swiftはなぜ構造体の使用を推奨するのですか?
値型には共有状態がないため、副作用が少なく予測しやすいからです。元の値が意図せず変更される危険がなく、マルチスレッド環境でも安全なので、バグの削減に役立ちます。
最初は単なる文法の違いだと思っていましたが、掘り下げるほど設計の問題だと分かりました。
今日この基準を身につけておけば、次のプロジェクトから迷いが減るはずです。値か共有か、まずこの問いを投げかけてみてください。

