class — とは何か、主要な概念とSwiftでの動作原理

著者: IT Sectr 公開日: 2026-06-17 読了時間: 8 分

ClassはSwift言語における参照型(reference type)であり、そのインスタンスは代入時にコピーされるのではなく、参照によって渡されます。構造体とは異なり、クラスは継承、デイニシャライゼーション、メモリ管理のための自動参照カウントARCをサポートしています。Swift Programming Language Guide, 2026によると、AppleのUIフレームワーク(UIKit、AppKit)で作業し、オブジェクトの共有アイデンティティを必要とするパターンを実装するにはclassが必要です。classとstructの選択は、Swiftにおける主要なアーキテクチャ上の決定の1つです。

重要なポイント

  • Class — Swiftの参照型で、変数は値そのものではなく、ヒープ内のオブジェクトへの参照を格納します。
  • 継承 — クラスは親クラスのプロパティとメソッドを継承し、overrideを使用してオーバーライドできます。
  • ARC — 自動参照カウントは、オブジェクトへの強参照がなくなったときにメモリを解放します。
  • Deinit — リソースをクリーンアップするために、オブジェクトが解放される前に呼び出される特別なメソッドです。
  • アイデンティティ — === および !== 演算子は、2つの変数が同じクラスインスタンスを参照しているかどうかを確認します。

Swiftにおけるclassとは?

Class — 継承と動的ディスパッチをサポートし、プロパティとメソッドを1つのエンティティにグループ化するSwiftの複合参照型です。structとは異なり、クラスインスタンスはヒープに作成され、変数はデータそのものではなく、このインスタンスへの参照を格納します。

クラス変数を別の変数に代入すると、両方がメモリ内の同じオブジェクトを参照します。一方の参照を介した変更は、もう一方の参照を通じて表示されます — これは参照型の基本的なプロパティであり、デリゲーション、監視、共有状態のパターンで使用されます。

Apple Swiftドキュメントによると、すべてのUIコンポーネントがUIViewとUIViewControllerから継承されるUIKitおよびAppKitで作業する唯一の方法はクラスです。さらに、オブジェクトのアイデンティティ(1つのオブジェクトへの2つの参照)と制御されたライフタイムを必要とするパターンを実装するには、クラスが必要です。

参照型としてのclass

参照型のセマンティクス — クラスの主要なプロパティです。クラスを新しい変数に代入するとき、Swiftはデータではなく参照をコピーします。同じインスタンスを参照するすべての変数は、その現在の状態を確認し、変更できます。この動作は、各変数が独立したコピーを取得する値型とは根本的に異なります。

swift
// 参照型セマンティクスの例
class User {
    var name: String
    init(name: String) { self.name = name }
}

let user1 = User(name: "Alice")
let user2 = user1           // user2 — 同じ参照
user2.name = "Bob"

print(user1.name)               // "Bob" — user2経由で変更!

// ===演算子によるアイデンティティチェック
print(user1 === user2)          // true — 同じオブジェクト

===(アイデンティティ)および !== 演算子は、2つの変数が同じクラスインスタンスを参照しているかどうかを確認します。これは、プロパティ値を比較する ==(等価性)とは異なります。=== 演算子はstructでは使用できません — 値型にはアイデンティティがありません。

クラスの継承

継承 — クラスが親クラスのプロパティとメソッドを引き継ぐことができるメカニズムです。Swiftでは、クラスは1つの親からのみ継承できます(単一継承)が、複数のプロトコルを実装できます。overrideキーワードを使用すると、継承されたメソッドまたはプロパティをオーバーライドできます。

基底クラスとサブクラス

別のクラスから継承しないクラスは、自動的に基底クラスになります(NSObjectと混同しないでください)。サブクラスは、名前の後にコロンを付けて親を指定します。サブクラスが親のメソッドをオーバーライドする場合、親の動作を維持するためにsuper.メソッド()を呼び出す必要があります — これはコンパイラの要件です。

Finalクラス

classの前のキーワードfinalは継承を防ぎます。コンパイラは静的ディスパッチを通じてfinalクラスのメソッド呼び出しを最適化し、パフォーマンスを向上させます。拡張を意図していないクラスにはfinalを使用してください — これにより意図が文書化され、コードが高速化されます。

swift
// Swiftにおけるクラス継承の例
class Vehicle {
    var speed: Double = 0

    func description() -> String {
        "Speed: \(speed) km/h"
    }
}

// CarはVehicleを継承
class Car: Vehicle {
    var brand: String = "Unknown"

    override func description() -> String {
        "\(brand) - \(speed) km/h"
    }
}

// Finalクラス — 継承を防ぐ
final class ElectricCar: Car {
    var batteryLevel: Double = 100
}

let tesla = ElectricCar()
tesla.brand = "Tesla"
tesla.speed = 120
print(tesla.description())  // "Tesla - 120.0 km/h"

継承は強力ですが責任を伴うメカニズムです。深い階層(5レベル以上)はメンテナンスとテストを複雑にします。継承なしで機能を再利用するには、拡張とプロトコル指向プログラミングを備えたプロトコルを使用してください — Appleが深いクラス階層の代替として推奨するアプローチです。

デイニシャライゼーションとメモリ管理

Swiftはクラスのメモリ管理にARC(自動参照カウント)を使用します。各クラスインスタンスには強参照カウンターがあります。新しい強参照が作成されるとカウンターが増加し、破棄されると減少します。カウンターがゼロになると、メモリが解放されます。

Deinit

Deinit — クラスインスタンスが解放される前に自動的に呼び出されるメソッドです。リソースを解放します:ファイルを閉じ、通知の購読を解除し、タイマーを停止します。Deinitはクラスでのみ使用可能です — 構造体と列挙型にはありません。

弱参照と非所有参照

強参照サイクル(retain cycles)を防ぐために、Swiftはweak参照とunowned参照を提供します。Weakはオプショナル参照で、オブジェクトが解放されると自動的にnilになります。Unownedは非オプショナルですが、現在のコンテキストよりも長く生存することが保証されているオブジェクトを参照します。典型的なretain cycleは親子関係で発生します:子が親への強参照を保持します。

swift
// ARCと弱参照の例
class Parent {
    var name: String
    var child: Child?

    init(name: String) { self.name = name }
    deinit { print("\(name) が解放されました") }
}

class Child {
    var name: String
    weak var parent: Parent?   // weakはretain cycleを防ぐ

    init(name: String) { self.name = name }
    deinit { print("\(name) が解放されました") }
}

var parent: Parent? = Parent(name: "Anna")
parent?.child = Child(name: "Mia")
parent?.child?.parent = parent

parent = nil  // 両方のオブジェクトが解放されました!
// weakがないとretain cycleが発生する

子オブジェクトから親への参照およびクロージャのキャプチャリストには常にweakを使用してください。Unownedは、オブジェクトが現在のコンテキストよりも長く生存することが確実な場合にのみ使用してください — unownedの誤用は、解放されたメモリにアクセスするとクラッシュを引き起こす可能性があります。

Class vs Struct: 主要な違い

classとstructの選択は、パフォーマンス、スレッドセーフティ、API設計に影響を与えるアーキテクチャ上の決定です。各ケースで正しい決定を下すために、主要な違いの表を検討してください。

特性classstruct
参照型値型(コピー)
メモリヒープ + ARCスタック / インライン
継承サポート(単一親)サポートしない
Deinitありなし
アイデンティティ (===)サポートサポートしない
Mutating不要(常にmutating)mutatingでのみ
Memberwise init生成されない自動生成される
スレッドセーフティ保証されない(共有状態)保証される(コピー)

共有アイデンティティ(コードの複数の部分が1つのオブジェクトで動作する)、継承、またはObjective-Cランタイムとの連携が必要な場合はクラスを使用してください。それ以外の場合は、構造体が推奨されます — より高速で、マルチスレッドコードで安全であり、メモリ管理が不要です。

Swiftでclassを使用するタイミング

Appleがデフォルトでstructを使用することを推奨しているにもかかわらず、いくつかの特定のシナリオではクラスが必要です。実践的な例を挙げてそれぞれを検討しましょう。

UIKitおよびAppKitコンポーネント

iOSおよびmacOSのすべてのUIコンポーネントは、UIView(iOS)またはNSView(macOS)から継承するクラスです。UIViewControllerを構造体に置き換えることはできません — リソースを解放するために継承とdeinitが必要です。UIKitで作業する場合は、コントローラー、ビュー、およびそのデリゲートにクラスを使用してください。

シングルトンと共有状態

シングルトンパターン(アプリケーション全体で1つのクラスインスタンス)は参照セマンティクスを必要とします。マネージャー:NetworkManager、SettingsManager、AnalyticsService — 通常は共有のstaticプロパティを持つクラスとして実装されます。構造体は各コピーが独立したインスタンスになるため適していません。

依存性注入と参照オブジェクト

オブジェクトが単一の真実の源であり、モジュール間で参照によって渡される必要がある場合は、classを使用してください。これは、ある場所でオブジェクトを変更したことがすべての依存コンポーネントに表示される必要がある状態管理に適用されます。SwiftUIのObservableObjectの場合、クラスが必須です。

swift
// ObservableObject — SwiftUIにclassが必要
import SwiftUI

class AppViewModel: ObservableObject {
    @Published var isLoggedIn: Bool = false
    @Published var username: String = ""

    func login(user: String) {
        isLoggedIn = true
        username = user
    }
}

// SwiftUI Viewでの使用
struct ContentView: View {
    @StateObject var viewModel = AppViewModel()

    var body: some View {
        Text(viewModel.isLoggedIn ? "ようこそ" : "ログイン")
    }
}

ルール:オブジェクトにアイデンティティ(2つの参照 -> 1つのオブジェクト)が必要な場合、単一インスタンスである場合、またはUIKit/Objective-Cで動作する必要がある場合 — classを選択してください。オブジェクトが単にデータを含む場合 — structを選択してください。

よくある質問

Swiftにおけるclassとは?

Classは継承、デイニシャライゼーション、メモリ管理のためのARCをサポートするSwiftの参照型です。クラスインスタンスはヒープに格納され、変数はオブジェクトへの参照を含み、そのコピーではありません。

Swiftでclassとstructの違いは?

Class — 参照型(参照で渡される)、継承とdeinitをサポート。Struct — 値型(コピーされる)、継承はサポートしないが、プロトコルを実装し、memberwise initを自動的に取得。Swiftはデフォルトの型としてstructを推奨しています。

SwiftにおけるARCとは?

ARC(自動参照カウント) — Swiftクラスのメモリ管理メカニズム。各インスタンスには強参照カウンターがあります。カウンターがゼロになるとメモリが解放されます。weak参照とunowned参照は、オブジェクト間のretain cyclesを防ぎます。

Swiftにおけるdeinitとは?

Deinit — メモリが解放される前に自動的に呼び出されるクラスメソッド。ファイルを閉じたり、通知の購読を解除したり、その他のクリーンアップ操作に使用されます。Deinitはクラスでのみ使用可能で、構造体にはありません。

Swiftでclassを使用するタイミングは?

UIKit/AppKitのUIコンポーネント、シングルトン、SwiftUIのObservableObject、共有アイデンティティを持つオブジェクト(delegate、observer)、およびObjective-Cランタイムで作業する場合はclassを使用してください。データモデル、DTO、設定にはstructが推奨されます。

まとめ

  • Classは参照渡しセマンティクスを持つSwiftの参照型です:1つのオブジェクトを指すすべての変数はその現在の状態を確認し、変更できます。
  • ARCは強参照カウントを通じてクラスのメモリを管理し、weakとunownedは親子関係やクロージャでのretain cyclesを防ぎます。
  • 継承によりクラスは親の動作を再利用およびオーバーライドできますが、深い階層(5レベル以上)はコードのメンテナンスを複雑にします。
  • Deinitはオブジェクトが解放されるときに実行され、リソース(ファイル、タイマー、NotificationCenterの購読)を解放するために必要です。
  • UIKitとAppKitはすべてのUIコンポーネント(UIView、UIViewController、そのデリゲート、データソース)にクラスを必要とします。
  • SwiftUIのObservableObject — SwiftUIは@Publishedと@StateObjectを参照によって変更を追跡するため、classが必須です。
  • Appleは新しいデータ型にはデフォルトの型としてstructを推奨しています — アイデンティティ、継承、またはObjective-Cとの統合が必要な場合にのみclassを使用してください。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください