instance_eval のスコープ と class_variable_set を使わないクラス変数の代入方法
ただし、ローカル変数だけは instance_eval の外側のスコープと共有します。
class Hoge
@@hoge = :hoge
def initialize
@test = :Nice_boat
end
end
o = :test
Hoge.new.instance_eval do
p o #=> :test
p @test #=> :Nice_boat
p @@hoge #=> uninitialized class variable @@hoge in Object (NameError)
endクラス変数も外側のスコープになってるような。module_eval のほうでは : version 1.6.8 以降でブロックが与えられた場合は、定数とクラス変数のスコープも外側のスコープになります。
って書いてあるけど、instance_eval もそうなのかな。
だとすると、ruby 1.8.3 で class_variable_set/get が実装されるまで、クラス変数に直接オブジェクトをセットする方法ってなかったのかな。Mac の ruby は 1.8.2 なのだけど、クラス変数を外から代入するのをどう書いたらいいかわからない……
とここで思いたって、たぶん同じことを ML できいたひとがいるだろうと class_variable_set を検索すると、[ruby-talk:144741] に "Why no class_variable_set?" という投稿があった。ML のアーカイブが全部 not found になっててリンクはれないけどキャッシュでみたところ、アクセサメソッドを定義してた。なるほど……
未定義にするところまで含めると以下のようにすれば一応できる。きもい。
class Hoge
@@hoge = :hoge
def t
@@hoge
end
end
o = :test
Hoge.class_eval %{
def self.hoge=(val)
@@hoge = val
end
}
Hoge.hoge = o
(class << Hoge; self; end).instance_eval do
remove_method(:hoge=)
end
p Hoge.new.t #=> :test
Hoge.hoge = :aaa # undefined method `hoge=' for Hoge:Class (NoMethodError)
なんか更めて読みなおしてみるとあたりまえすぎる……べつに定義されていないなら、class_variable_set/get を定義すればいいだけじゃん
あれでも、結局 eval するはめになってだめか。おれあたまわるい……もうやだ