C++が分かる人向けにSwiftのstructとclassの違いを整理する

Swiftでは struct をかなりよく使います。

C++経験者だと、structclass はアクセス指定のデフォルトが違うくらい、という感覚が残っているかもしれません。

Swiftではそこがかなり違います。

公式でも、structures and classesは似た機能を持つ一方で、classには継承や参照セマンティクスがあると説明されています。

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures/

structは値型

Swiftの struct は値型です。

struct Point {
    var x: Int
    var y: Int
}

var a = Point(x: 1, y: 2)
var b = a

b.x = 10

print(a.x) // 1
print(b.x) // 10

b = a で同じものを参照しているわけではありません。

C++の普通の値コピーに近いです。

Point a{1, 2};
Point b = a;
b.x = 10;

classは参照型

Swiftの class は参照型です。

final class Counter {
    var value = 0
}

let a = Counter()
let b = a

b.value = 10

print(a.value) // 10

ab は同じインスタンスを指しています。

C++でいうポインタや shared_ptr 的な共有参照に近い感覚です。

mutatingが必要になる

Swiftのstructで自分自身を書き換えるメソッドには mutating が必要です。

struct Counter {
    var value = 0

    mutating func increment() {
        value += 1
    }
}

これは「このメソッドは値を変更する」という印です。

C++では非constメンバ関数なら変更できますが、Swiftではstructのメソッドはデフォルトでselfを変更できません。

まずstructで考える

Swiftでは、データを表す型はまずstructで作ることが多いです。

struct User {
    let id: Int
    var name: String
}

classにするのは、参照として共有したい理由がある場合です。

  • 同じインスタンスを複数箇所から更新したい
  • 継承が必要
  • Objective-CやAppleフレームワークとの都合がある
  • identityを扱いたい

このあたりがないなら、structで十分なことが多いです。

まとめ

Swiftの structclass は、C++より意味の差が大きいです。

  • struct は値型
  • class は参照型
  • structで自身を変更するメソッドには mutating
  • データ表現はまずstructで考える
  • 共有・継承・identityが必要ならclassを使う

C++の struct/class の違いを持ち込むより、「値として扱うか、参照として共有するか」で見ると整理しやすいです。

関連記事

参考