Uncategorized Archive

一年前に引っかかった話がドラフトとして眠っていたのでポスト。

 

attr_accessorで定義したsetterメソッドを同一クラス内から呼び出す時、期待するように値が更新されず困っていたのですが(以下参照)、

#!/usr/bin/env ruby

class InstanceVariableEval

  attr_accessor :val

  def initialize
    @val = "initial data"
  end

  def set_from_instance_method_through_accessor
    val = "set_from_instance_method_through_accessor"
  end

end


a = InstanceVariableEval.new

puts a.val
a.set_from_instance_method_through_accessor
puts a.val
a.val = "set_through_accessor"
puts a.val

## Following is the output. I can't understand why val is not updated by the method "set_from_instance_method_through_accessor".
# initial data
# initial data
# set_through_accessor

shigeyas先生に教えて頂き解決することが出来ました。

Rubyは、setter系のメソッドを同一クラス内から呼び出す場合(代入っぽい呼び出しを行う場合)、レシーバとしてselfを必要とするようです。selfを付けない場合、ローカル変数と区別がつかないために、ローカル変数の宣言兼代入として扱われてしまうのです。C#のプロパティだと、この問題に直面しにくいのは、C#では変数を使用するにあたって、宣言が必要なため、setter系のメソッドの呼び出しをローカル変数の宣言兼代入と誤認することがないためです。既に同名のローカル変数がその呼び出し元メソッド内で宣言されている場合は、thisをレシーバとして明示して呼び出しをする必要がある点は一緒ですね。