StructはSwift言語における値型(value type)であり、そのインスタンスはコードの各部分間で渡される際にコピーされます。クラスとは異なり、構造体は継承をサポートしませんが、プロトコルを実装し、プロパティとメソッドを持ち、ARCなしで予測可能なメモリ管理を提供します。Swift Programming Language Guide, 2026によると、structはSwiftの基本的な構成要素であり、Int、String、Array、Dictionaryといった標準型でさえ構造体として実装されています。言語はデータモデリングの優先選択として構造体を推奨しています。
重要なポイント
Struct(構造体)は、関連するプロパティとメソッドを単一のエンティティにグループ化するSwiftの複合データ型です。クラスとは異なり、構造体は値型です。関数に渡したり新しい変数に代入したりすると、元のオブジェクトへの参照ではなく、構造体の独立したコピーが作成されます。
Swiftはすべてのプリミティブ型に構造体を使用します:Int、Double、String、Bool、Array、Dictionary、Set。つまり、基本的なIntでさえ構造体のように振る舞い、代入時にコピーが作成されます。開発者は任意のプロパティとメソッドのセットで独自の構造体を定義できます。
Swift Evolution(SE-0143)によると、標準型を構造体として実装する決定は、パフォーマンスと予測可能性に基づいています。値型は参照サイクルを作成せず、ARC参照カウントを必要とせず、コピーの変更がオリジナルに影響しないことを保証します。これはマルチスレッドシナリオでのデータの不変性にとって極めて重要です。
値型のセマンティクスがstructとclassの主な違いです。構造体を新しい変数に代入したり関数に渡したりすると、Swiftはすべてのデータの独立したコピーを作成します。コピーへの変更はオリジナルに影響を与えず、参照型に特有の副作用を排除します。
// 値型セマンティクスの例
struct Point {
var x: Double
var y: Double
}
var p1 = Point(x: 10, y: 20)
var p2 = p1 // p2はp1の独立したコピー
p2.x = 99 // p2のみ変更
print(p1.x) // 10 — p1は変更なし
print(p2.x) // 99
Swiftはコピーの最適化にCopy-on-Write(COW)を使用します。複数の変数が同じ構造体を参照していても、どれもデータを変更しない場合、実際のコピーは発生しません。Swiftは最初の変更まで変数間でメモリを共有し、その時点で実際のコピーが作成されます。これにより過剰な割り当て操作を防ぎ、コレクションの操作を高速化します。
デフォルトでは、構造体のメソッドはそのプロパティを変更できません。Swiftは変更を行うメソッドに明示的なmutatingキーワードを要求します。この制限は偶発的な変更を防ぎ、コードを予測可能にします。メソッドがmutatingとマークされていない場合、構造体を変更しないことが保証されます。
メソッドの前にmutatingキーワードを追加すると、Swiftは構造体のプロパティに新しい値を書き込む能力を得ます。実際、メソッドはself = を介して構造体インスタンスを完全に新しいものに置き換えることさえできます。このメカニズムは、例えばOption型やResult型で使用されています。
// mutatingメソッドを持つstruct
struct Counter {
private var value: Int = 0
// Mutatingメソッド — プロパティを変更可能
mutating func increment() {
value += 1
}
// Mutatingメソッドはselfを完全に置き換え可能
mutating func reset() {
self = Counter()
}
// 非mutatingメソッド — 読み取り専用
func currentValue() -> Int {
return value
}
}
var counter = Counter()
counter.increment()
print(counter.currentValue()) // 1
counter.reset()
print(counter.currentValue()) // 0
Mutatingのルール:構造体はvarで宣言する必要があり、letでは宣言できません。定数構造体はmutatingメソッドを呼び出せません。コンパイラはビルド時にこれをチェックし、let定数でmutatingメソッドを呼び出そうとするとコンパイルエラーになります。
structとclassの選択は、Swiftにおける基本的な判断の一つです。どちらの型もプロパティ、メソッド、イニシャライザを持ち、プロトコルを実装できますが、メモリセマンティクス、継承、ライフサイクル管理に根本的な違いがあります。
| 特性 | struct | class |
|---|---|---|
| 型 | 値型(コピーされる) | 参照型(参照) |
| 継承 | サポートしない | サポートする |
| ARC / 参照カウント | 不要 | ARC必要 |
| デイニシャライゼーション | サポートしない | deinitをサポート |
| 定数でのプロパティ変更 | varのみ可能 | letでも可能(参照は定数) |
| 型キャスト | サポートしない | サポートする |
| コレクション内の格納 | 直接格納(値) | 参照として格納(ポインタ) |
構造体は、データが継承を必要としない場合、共有アイデンティティを持つべきでない場合(例:座標、サイズ、設定)、モジュール間で渡される場合に適しています。クラスはUIコンポーネント(UIView、UIViewController)、シングルトン、共有アイデンティティを持つオブジェクトに選ばれます。
AppleはSwiftでのデータモデリングにstructをデフォルト型として使用することを推奨しています。構造体は、予測可能なコピーセマンティクスと参照カウントのオーバーヘッドがないため、ほとんどのシナリオに適しています。structが最適な選択となる典型的なケースを見てみましょう。
エンティティが継承を必要とせずにデータを含む場合(Product、User、Order、Point)、structを使用します。コンパイラは自動的にメンバーワイズイニシャライザを生成するため、手動でinitを書く必要はありません。EquatableとHashableも、すべてのプロパティがこれらのプロトコルに準拠する構造体に対して自動的に実装されます。
作成後に変更されない設定やフラグには、classよりもstructが適しています。定数(let)構造体はすべてのネストされたフィールドの不変性を保証しますが、classではこれは参照にのみ適用され、オブジェクトの内容には適用されません。
値セマンティクスにより、構造体はマルチスレッド環境で安全です。各スレッドはデータの独立したコピーを取得し、他のスレッドに影響を与えません。値型ではスレッド間のデータ競合が不可能であり、SwiftUIのモデルではstructが推奨されます(ObservableObjectはclassが必要ですが、@Stateはstructを使用します)。
// データモデルでのstruct使用例
struct User: Codable, Identifiable {
let id: UUID
var name: String
var email: String
var isPremium: Bool
// 算出プロパティ — 非mutating
var displayName: String {
isPremium ? "\(name) ⭐️" : name
}
}
// 自動メンバーワイズイニシャライザ
let user = User(
id: UUID(),
name: "Alice",
email: "alice@example.com",
isPremium: true
)
// マルチスレッドでも安全なコピー
var userCopy = user
userCopy.isPremium = false
// user.isPremiumはtrueのまま
継承(UIKit/AppKitコンポーネント)、共有アイデンティティ(delegate、observer)、または制御されたオブジェクトライフサイクル(deinit)が必要な場合はclassを使用してください。それ以外のすべてにはstructを使用してください。
よくある質問
StructはSwiftの値型で、コードの各部分間で渡される際にコピーされます。構造体はプロパティ、メソッド、イニシャライザを持ち、プロトコルを実装できます。Swiftの基本型(Int、String、Array)は構造体として実装されています。
Structは値型(代入時にコピー)、継承をサポートせず、ARC不要。Classは参照型(参照で渡される)、継承、デイニシャライゼーション、参照カウントをサポート。開発者はstructをデフォルト型として推奨しています。
Mutatingは、構造体のメソッドがそのプロパティを変更できることを示すキーワードです。mutatingなしでは、コンパイラはフィールドの変更を禁止します。mutatingメソッドはvarで宣言された変数でのみ呼び出せ、letでは呼び出せません。
Copy-on-Write(COW)は、構造体に対するSwiftの最適化で、実際のデータコピーを最初の変更まで遅延させます。すべての変数が構造体を読み取るだけの間は、単一のメモリ領域を共有します。これにより大きなコレクションを扱う際のパフォーマンスが向上します。
継承のないデータモデル、設定、DTO、マルチスレッドシナリオにはstructを使用。UIKit/AppKit UIコンポーネント、シングルトン、共有アイデンティティを持つエンティティ(delegate、observer)、デイニシャライゼーションが必要なオブジェクトにはclassを使用。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。