selfの暗黙的な参照について

Rubyのselfで軽く詰まったのでメモ

自身の所属するインスタンスに対してアクセスが可能になる所謂 this の様な機能。
基本的には暗黙的な参照を行うわけだが案外落とし穴になったりする。

class People

  attr_accessor :name
  attr_accessor :age

  def set_name(input_name)
    name = input_name
    puts "#{name}が挿入されました"
  end

  def set_age(input_age)
    age = input_age
    puts "#{age}が挿入されました"
  end

end

engineer = People.new

engineer.age = 22
engineer.name = 'エンジニア'

engineer.set_name('engineer')
engineer.set_age('20')

puts "氏名:#{engineer.name}、年齢:#{engineer.age}"

# engineerが挿入されました
# 20が入されました
# 氏名:エンジニア、年齢:22


ここでの出力結果を見ての通りメソッドはcallされているのに何故か反映されていない。
原因はここ

name = input_name

age = input_age

基本的にRubyではインスタンス変数に対してアクセスされた際は暗黙的にselfをとして認識する。
ところが、参照以外...つまり代入処理などが実行される際にはローカル変数として定義してしまう。

それを裏付けるのが代入時のメッセージ。
ここで代入されている name age はインスタンス変数ではなくローカル変数として宣言されたため、
今回の様なメッセージが出力されているわけだ。

対策としては以下の様な修正をすればいい

class People

  attr_accessor :name
  attr_accessor :age

  def set_name(input_name)
    self.name = input_name
    puts "#{name}が挿入されました"
  end

  def set_age(input_age)
    self.age = input_age
    puts "#{age}が挿入されました"
  end

end

engineer = People.new

engineer.age = 22
engineer.name = 'エンジニア'

engineer.set_name('engineer')
engineer.set_age('20')

puts "氏名:#{engineer.name}、年齢:#{engineer.age}"

# engineerが挿入されました
# 20が挿入されました
# 氏名:engineer、年齢:20

要は明示的にselfを設定してやればいい。
こうすることで明示的にインスタンス変数に対して代入が実行される。
相変わらず"暗黙的"って便利だけど怖い