初期化前のインスタンス変数を参照すると警告なしで nil になる
initializeで値を設定し忘れたインスタンス変数は、エラーにも警告にもならず単にnilとして扱われます。存在しないローカル変数がNameErrorになるのとは対照的です。
なぜエラーが出ないのか
出力: Balance:
(エラーなし)- Rubyは何も報告しません。文法として正しいためです
出力: Balance:- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 class Account 2 def initialize(balance) 3 balance = balance ^ 4 end 5 6 def show 7 puts "Balance: #{@balance}" 8 end 9 end 10 11 Account.new(500).show
出力: Balance:
@を付けずに代入するとローカル変数になり、initializeを抜けた時点で消えます。@balanceは初期化されないままnilで残ります。
直し方: balance を @balance にします。
広告
広告スロット(未設定)
パターン2
1 class Player 2 def initialize(score) 3 score = score ^ 4 end 5 6 def show 7 puts "Score: #{@score}" 8 end 9 end 10 11 Player.new(80).show
出力: Score:
エラーにも警告にもならないため、出力を確認するまで初期化し忘れに気づけません。
直し方: score を @score にします。
パターン3
1 class Character 2 def initialize(level) 3 level = level ^ 4 end 5 6 def show 7 puts "Level: #{@level}" 8 end 9 end 10 11 Character.new(5).show
出力: Level:
インスタンス変数のつもりで書いたローカル変数は、メソッドを抜けると同時に消えてしまいます。
直し方: level を @level にします。
パターン4
1 class Cart 2 def initialize(count) 3 count = count ^ 4 end 5 6 def show 7 puts "Count: #{@count}" 8 end 9 end 10 11 Cart.new(3).show
出力: Count:
未初期化のインスタンス変数はNameErrorにならず、静かにnilとして扱われます。
直し方: count を @count にします。
パターン5
1 class Order 2 def initialize(total) 3 total = total ^ 4 end 5 6 def show 7 puts "Total: #{@total}" 8 end 9 end 10 11 Order.new(999).show
出力: Total:
@の付け忘れは見た目がよく似ているため、コードを読むだけでは見落としやすいミスです。
直し方: total を @total にします。
よくある誤解
「初期化していないインスタンス変数を参照すればエラーになるはず」という思い込みは誤りです。Rubyのインスタンス変数は未初期化でもnilという値を持つ変数として静かに扱われ、後続の計算にnilが紛れ込みます。
まとめ
初期化前のインスタンス変数を参照すると警告なしで nil になるは中級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。