Rubyのsetterメソッドは特別扱いされる。
Rubyのsetterメソッドの振る舞いを理解していなくて、ちょっとビックリしたので。
まずはsetterの基本から。
def abc=(a) puts "abc setter" end abc = 123
これは何も表示しません。abc = 123はローカル変数abcを定義しています。
def abc=(a) puts "abc setter" end self.abc = 123
こうすると"abc setter"が表示されます。同じようにgetterを足してみると……
def abc=(a) puts "abc setter" end def abc puts "abc getter" end self.abc = 123 self.abc
最後の行でエラーになります。
private method `abc' called for main:Object (NoMethodError)
トップレベルのメソッドはデフォルトでプライベートなので、self.で修飾して実行できません。でもsetterは特別。self.abc = 123と書けます。
同じことをクラスを定義して試してみると、
class Abc def test self.xyz=123 xyz end private def xyz=(a) puts "xyz setter" end def xyz puts "xyz getter" end end o = Abc.new o.test o.xyz = 123
結果は以下の通り。
$ ruby ./tmp.rb xyz setter xyz getter ./tmp.rb:21: private method `xyz=' called for #<Abc:0x1002fb10> (NoMethodError)
ポイントは、
- self.xyz=123 を xyz=123 とするとローカル変数の定義になり、setterは呼ばれない(privateかどうかに関わらず)。
- xyz を self.xyzに変えるとエラー。setterとgetter(普通のメソッド)は扱いが違う。
- 最後の o.xyz = 123 はエラー。privateなxyz=に対して、中で self.xyz=123 と書けても、外から o.xyz=123 とは書けるわけではない。
まあprivateなsetter/getterを使う機会はあんまり無いかもしれませんが……。
参考
Thu Feb 20 04:07:06 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net> * parse.y (attrset): "self.foo=x" can be legal even when "foo=" is private.