Swiftの計算プロパティをC++のgetter感覚で読むときに気をつけること
Swiftの var area: Int { width * height } みたいな書き方、最初は少し不思議に見えます。
C++でいうgetter関数に近いですが、Swiftではプロパティとして扱います。
公式でも、プロパティにはstored propertyとcomputed propertyがあると説明されています。
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties/
stored propertyとcomputed property
stored propertyは値を保持します。
struct Size {
var width: Int
var height: Int
}
computed propertyは値を保持せず、アクセス時に計算します。
struct Size {
var width: Int
var height: Int
var area: Int {
width * height
}
}
area という保存領域があるわけではありません。
let size = Size(width: 12, height: 8)
print(size.area) // 96
C++で書くなら、だいたいこの感覚です。
struct Size {
int width;
int height;
int area() const {
return width * height;
}
};
Swiftでは呼び出し側が size.area になるので、値のように読めます。
setも書ける
computed propertyには get と set を書けます。
struct Temperature {
var celsius: Double
var fahrenheit: Double {
get {
celsius * 9 / 5 + 32
}
set {
celsius = (newValue - 32) * 5 / 9
}
}
}
newValue はsetterに渡ってくる新しい値です。
var temp = Temperature(celsius: 0)
temp.fahrenheit = 212
print(temp.celsius) // 100
これはC++のsetterに近いです。
重い処理は置きすぎない
computed propertyは見た目が値なので、読む側は軽い処理だと思いがちです。
var summary: String {
items.map(\.name).joined(separator: ", ")
}
このくらいならまだ読めます。
ただ、ネットワークアクセス、ファイル読み込み、重い検索などを入れると、呼び出し側からコストが見えません。
var remoteValue: String {
// これはやめた方がいい
}
Swiftでも、重い処理や失敗する処理はメソッドにした方が自然です。
func loadRemoteValue() async throws -> String {
...
}
setを書けるからといって何でも書かない
setter付きcomputed propertyは便利ですが、状態変更が見えにくくなることがあります。
user.displayName = "new name"
これが単純代入なのか、複数フィールドを更新しているのか、外からは見えません。
値の変換や別表現として自然なものだけに絞ると読みやすいです。
まとめ
Swiftの計算プロパティは、C++のgetter/setterに近いですが、呼び出し側では値のように見えます。
- stored propertyは値を保持する
- computed propertyはアクセス時に計算する
- 軽い派生値ならcomputed propertyでよい
- 重い処理、失敗する処理、非同期処理はメソッドに寄せる
() が付かないぶん、呼び出し側からコストが見えにくい。この点だけ意識しておくと扱いやすいです。


