Ruby 1.9 でのクラス変数の初期化の妙な(?)挙動
AP4R や reliable-msg が Ruby 1.9 で動くか試していた際に気づいたことです。
1.9 での変更点を追いきれていませんが、ちょっと不思議な感じだったので...
言葉で説明しづらいので、以下ソースw
% cat test_class_variable.rb class Test class << self def call_class_method @@hoge = "hello" end def do call_class_method puts @@hoge end end def initialize Test.call_class_method puts @@hoge end end Test.do Test.new
上記コードを Ruby 1.8 と 1.9 で実行すると以下の結果が得られます。
クラス変数 @@hoge はクラスメソッド内にて初期化 & 代入されています。
で、1.8 では初期化が認識されますが、1.9 では (微妙に) 駄目なようです?
% ruby -v test_class_variable.rb ruby 1.8.6 (2007-09-24 patchlevel 111) [i686-darwin8.11.1] hello hello % ruby19 -v test_class_variable.rb ruby 1.9.0 (2007-12-25 revision 14709) [i686-darwin8.11.1] hello test_class_variable.rb:15:in `initialize': uninitialized class variable @@hoge in Test (NameError) from test_class_variable.rb:20:in `new' from test_class_variable.rb:20:in `<main>'
モジュールでも似たような挙動です。
モジュール関数としては公開したくないメソッドがあると、こんな書き方になるんじゃないでしょうか。
% cat test_class_variable_in_module.rb module Test class << self private def call_class_method @@hoge = "hello" end end def do call_class_method puts @@hoge end module_function :do end Test.do
% ruby -v test_class_variable_in_module.rb ruby 1.8.6 (2007-09-24 patchlevel 111) [i686-darwin8.11.1] hello % ruby19 -v test_class_variable_in_module.rb ruby 1.9.0 (2007-12-25 revision 14709) [i686-darwin8.11.1] test_class_variable_in_module.rb:11:in `do': uninitialized class variable @@hoge in Test (NameError) from test_class_variable_in_module.rb:17:in `<main>'
ちなみに、あらかじめ (nil でも代入して) 初期化してみたらエラーにはなりませんでした。
その後、クラスメソッド内での代入結果はもちろん反映されます。
以上、Ruby 1.9 で uuid-1.0.4 を使おうとしていて気づいたことでした。
追記: このあたりの変更が絡んでるっぽい?
- Matzにっき(2007-01-04)
http://www.rubyist.net/~matz/20070104.html#p03
"メソッド内部のクラス変数はそのメソッドを定義するクラスに所属する。 特異メソッドの場合には特異クラスに(1.8とは非互換)。"