Swiftのコードを読んでいると、_book
や_count
のようにアンダースコア(_)で始まる変数を見かけることがあります。この記事では、Swiftにおけるアンダースコア付き変数の意味と使い方、そして特別なケースについて初心者の方にもわかりやすく解説します。
_付き変数とは
Swiftでは、変数名の先頭にアンダースコア(_)をつけることができます。
var book = "Swift入門" // 通常の変数
var _book = "Swift入門" // アンダースコア付きの変数
どちらも文法的には有効な変数名ですが、命名規則として異なる意味を持たせることが一般的です。
_付き変数の基本的な意味
命名規則としての役割
_
で始まる変数は、慣習的に以下のような意味で使われます。
内部実装を表す プログラマーの間では、「この変数は内部的に使うもので、外部から直接アクセスすべきではない」という暗黙の了解があります。
class BookStore {
private var _books: [String] = [] // 内部用の変数
var books: [String] {
return _books
}
}
ただし、重要なポイントとして、アンダースコア自体に特別な機能はありません。単なる命名規則です。
アクセス制御は別途必要
_
をつけただけでは、変数はプライベートになりません。
// これだけではプライベートにならない
var _internalValue = 10 // 外部からもアクセス可能
// privateキーワードが必要
private var _internalValue = 10 // これで初めてプライベート
_付き変数は宣言が必要か?
多くの初心者が疑問に思うのが、「_付き変数は自動的に使えるのか?」という点です。
基本ルール:宣言が必要
**答えは「NO」です。**通常の変数と同じように、使う前に必ず宣言が必要です。
// ❌ エラー:宣言していないので使えない
print(_book)
// エラーメッセージ: Use of unresolved identifier '_book'
// ✅ 正しい:まず宣言する
var _book = "Swift入門"
print(_book) // "Swift入門"
_book
は特別な変数ではなく、book
やmyVariable
と全く同じ通常の変数名です。
_付き変数の主な使い方
1. プライベート変数の命名規則
クラスやstructの内部で使う変数に_
をつけることで、「これは内部実装の詳細」であることを示します。
class Temperature {
private var _celsius: Double = 0.0 // 内部変数
var celsius: Double {
get {
return _celsius
}
set {
_celsius = newValue
print("温度が\(_celsius)度に変更されました")
}
}
}
let temp = Temperature()
temp.celsius = 25 // ✅ OK
// temp._celsius = 25 // ❌ エラー:privateなのでアクセスできない
2. バッキング変数として使用
計算プロパティの背後で実際のデータを保存する変数として使います。
class Person {
private var _name: String = ""
var name: String {
get {
return _name
}
set {
// 空白を削除してから保存
_name = newValue.trimmingCharacters(in: .whitespaces)
}
}
}
let person = Person()
person.name = " 太郎 "
print(person.name) // "太郎"(空白が削除されている)
3. 遅延初期化のパターン
データを必要になるまで読み込まない場合に使います。
class DataManager {
private var _data: [String]?
var data: [String] {
if _data == nil {
_data = loadData() // 初回アクセス時のみロード
}
return _data!
}
private func loadData() -> [String] {
print("データを読み込んでいます...")
return ["データ1", "データ2", "データ3"]
}
}
let manager = DataManager()
print("マネージャー作成")
print(manager.data) // ここで初めて"データを読み込んでいます..."が表示される
単独のアンダースコア(_)の特別な使い方
変数名として単独の_
を使う場合、「この値は使わない」という意味になります。これはSwiftの言語機能として特別な意味を持ちます。
タプルの一部を無視
let userInfo = ("太郎", "taro@example.com", 25)
// emailは使わないので_で無視
let (name, _, age) = userInfo
print(name) // "太郎"
print(age) // 25
// print(_) // ❌ エラー:_は値として使えない
ループで使わないインデックス
// インデックスを使わない場合
for _ in 0..<5 {
print("Hello")
}
// 配列の要素を使わない場合
let numbers = [1, 2, 3, 4, 5]
numbers.forEach { _ in
print("処理実行")
}
関数の引数を無視
func performAction(_ handler: (String) -> Void) {
handler("データ")
}
// 引数を使わない場合
performAction { _ in
print("引数は無視して処理だけ実行")
}
Property Wrappersでの特殊なケース
SwiftUIなどで使われるProperty Wrappersを使う場合、_
付き変数に特別な動作があります。
@Stateの例
import SwiftUI
struct CounterView: View {
@State var count = 0 // countを宣言
var body: some View {
VStack {
Text("カウント: \(count)")
Button("増やす") {
count += 1 // 通常のアクセス
}
Button("直接アクセス") {
// _countが自動的に利用可能!
_count.wrappedValue += 1
}
}
}
}
Property Wrappersの仕組み
@State
などのProperty Wrapperを使うと、内部的に以下のようなコードが生成されます。
// あなたが書くコード
@State var isOn = false
// 内部的に生成されるコード(イメージ)
private var _isOn = State(wrappedValue: false)
var isOn: Bool {
get { _isOn.wrappedValue }
set { _isOn.wrappedValue = newValue }
}
このため、@State var count
と宣言すると、自動的に_count
という変数が利用可能になります。
Property Wrappersでの_の使い道
struct SettingsView: View {
@State var username = ""
var body: some View {
VStack {
TextField("ユーザー名", text: $username)
Button("リセット") {
// Stateの実体に直接アクセス
_username = State(wrappedValue: "")
}
Button("バインディングを渡す例") {
// $usernameはBindingを返す
// 内部的には_username.projectedValueにアクセス
someFunction(binding: $username)
}
}
}
func someFunction(binding: Binding<String>) {
// バインディングを使った処理
}
}
_付き変数を使う際の注意点
1. 乱用しない
すべての内部変数に_
をつける必要はありません。本当にプライベートであることを強調したい場合のみ使いましょう。
// 過剰な使用例
class Example {
private var _value1: Int = 0
private var _value2: String = ""
private var _value3: Bool = false
// ...全部_をつける必要はない
}
// シンプルな方が良い場合も
class Example {
private var value1: Int = 0
private var value2: String = ""
private var value3: Bool = false
}
2. 一貫性を保つ
プロジェクト内で命名規則を統一することが重要です。
// ❌ 一貫性がない
class InconsistentExample {
private var _privateValue1: Int = 0
private var privateValue2: String = "" // _がない
private var _anotherValue: Bool = false
}
// ✅ 一貫性がある
class ConsistentExample {
private var _privateValue1: Int = 0
private var _privateValue2: String = ""
private var _anotherValue: Bool = false
}
3. 現代的なSwiftでは減少傾向
Swift 5.1以降、Property Wrappersの導入により、_
付き変数を手動で書く機会は減っています。
// 古いパターン
class OldStyle {
private var _title: String = ""
var title: String {
get { _title }
set { _title = newValue }
}
}
// 新しいパターン(Property Wrapper使用)
class NewStyle {
@Published var title: String = ""
}
実践的なコード例
例1:入力バリデーション付きプロパティ
class User {
private var _age: Int = 0
var age: Int {
get {
return _age
}
set {
// 0〜150の範囲でのみ設定可能
if newValue >= 0 && newValue <= 150 {
_age = newValue
} else {
print("エラー:無効な年齢です")
}
}
}
}
let user = User()
user.age = 25
print(user.age) // 25
user.age = 200 // エラー:無効な年齢です
print(user.age) // 25(変更されない)
例2:変更通知機能付きプロパティ
class Observable {
private var _value: String = "" {
didSet {
notifyObservers()
}
}
var value: String {
get { _value }
set { _value = newValue }
}
private func notifyObservers() {
print("値が\(_value)に変更されました")
}
}
let observable = Observable()
observable.value = "新しい値" // "値が新しい値に変更されました"
例3:キャッシュ機能
class ExpensiveCalculator {
private var _cachedResult: Int?
private var _lastInput: Int?
func calculate(_ input: Int) -> Int {
// 前回と同じ入力ならキャッシュを返す
if let lastInput = _lastInput,
lastInput == input,
let cached = _cachedResult {
print("キャッシュを使用")
return cached
}
// 複雑な計算(イメージ)
print("計算を実行")
let result = input * input
// 結果をキャッシュ
_lastInput = input
_cachedResult = result
return result
}
}
let calculator = ExpensiveCalculator()
print(calculator.calculate(5)) // "計算を実行" → 25
print(calculator.calculate(5)) // "キャッシュを使用" → 25
print(calculator.calculate(10)) // "計算を実行" → 100
よくある質問
Q1: _をつけると自動的にprivateになりますか?
A: いいえ、なりません。private
キーワードを明示的につける必要があります。
var _value = 10 // publicなまま
private var _value = 10 // これでprivate
Q2: Property Wrapperを使わない場合、_付き変数は自動生成されますか?
A: いいえ、されません。通常の変数と同じように宣言が必要です。
Q3: いつ_をつけるべきですか?
A:
- プロパティのバッキング変数として使う場合
- 内部実装であることを明示したい場合
- チームやプロジェクトのコーディング規約に従う場合
ただし、必須ではなく、シンプルに書ける場合は_
を省略することも多いです。
Q4: SwiftUIで@Stateを使うとき、_countと$countの違いは?
A:
count
:値に直接アクセス(Int型など)_count
:State構造体の実体にアクセス(State<Int>型)$count
:Bindingにアクセス(Binding<Int>型)
@State var count = 0
count // Int型の値
_count // State<Int>型
$count // Binding<Int>型
まとめ
Swiftにおける_付き変数について、重要なポイントをまとめます。
基本的なルール
_
は変数名の一部で、特別な機能はない- 通常の変数と同じように宣言が必要
- 命名規則として「内部実装」を表すために使われる
private
キーワードとは別物
単独の_の特別な用途
- タプルやループで「使わない値」を表す
- これはSwiftの言語機能として特別な意味を持つ
Property Wrappersでの例外
@State var count
のように宣言すると_count
が自動的に利用可能になる- これはProperty Wrapperの機能
使用時の推奨事項
- 必要な場面でのみ使用する
- プロジェクト内で一貫性を保つ
- 現代的なSwiftでは、Property Wrappersなどの機能により使用頻度は減少傾向
実践のヒント
- バッキング変数として使う場合は有効
- 入力バリデーションやキャッシュ機能の実装に便利
- ただし、シンプルに書ける場合は無理に使わなくてもOK
_付き変数は、適切に使えばコードの意図を明確に伝えることができる便利な命名規則です。ただし、乱用せず、本当に必要な場面で使うことを心がけましょう。
まずは他の人が書いたSwiftコードを読んで、どのような場面で_が使われているかを観察することから始めてみてください。実際のコードの中で使い方を学ぶことで、自然と適切な使い分けができるようになります。