MENU

【Swift入門】_付き変数とは?アンダースコアの使い方を初心者向けに解説

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は特別な変数ではなく、bookmyVariableと全く同じ通常の変数名です。

_付き変数の主な使い方

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&lt;Int>型
$count         // Binding&lt;Int>型

まとめ

Swiftにおける_付き変数について、重要なポイントをまとめます。

基本的なルール

  • _は変数名の一部で、特別な機能はない
  • 通常の変数と同じように宣言が必要
  • 命名規則として「内部実装」を表すために使われる
  • privateキーワードとは別物

単独の_の特別な用途

  • タプルやループで「使わない値」を表す
  • これはSwiftの言語機能として特別な意味を持つ

Property Wrappersでの例外

  • @State var countのように宣言すると
  • _countが自動的に利用可能になる
  • これはProperty Wrapperの機能

使用時の推奨事項

  • 必要な場面でのみ使用する
  • プロジェクト内で一貫性を保つ
  • 現代的なSwiftでは、Property Wrappersなどの機能により使用頻度は減少傾向

実践のヒント

  • バッキング変数として使う場合は有効
  • 入力バリデーションやキャッシュ機能の実装に便利
  • ただし、シンプルに書ける場合は無理に使わなくてもOK

_付き変数は、適切に使えばコードの意図を明確に伝えることができる便利な命名規則です。ただし、乱用せず、本当に必要な場面で使うことを心がけましょう。

まずは他の人が書いたSwiftコードを読んで、どのような場面で_が使われているかを観察することから始めてみてください。実際のコードの中で使い方を学ぶことで、自然と適切な使い分けができるようになります。

プログラミングの独学におすすめ
プログラミング言語の人気オンラインコース
独学でプログラミングを学習している方で、エラーなどが発生して効率よく勉強ができないと悩む方は多いはず。Udemyは、プロの講師が動画で実際のプログラムを動かしながら教えてくれるオンライン講座です。講座の価格は、セール期間中には専門書籍を1冊買うよりも安く済むことが多いです。新しく学びたいプログラミング言語がある方は、ぜひUdemyでオンライン講座を探してみてください。
目次