From: swec@... Date: 2010-04-17T16:07:16+09:00 Subject: [ruby-list:47026] Re: [Q] instance_eval 中でのクラス変数のアクセス 東(質問者)です。 > クラス変数を外部から自由に扱いたい(+それでかまわ > ない)というのであるなら、クラス変数へのアクセサを > 定義するのが吉。 たしかに、そうですね。 最初の検証プログラムでも、func1()の中ではクラス変数に アクセスできているので、そこで気づくべきでした。 実際のプロジェクトでも、アクセッサ定義してやって問題回避が うまくできました。 アドバイス、ありがとうございました。 ただ、アクセッサ実験中に少しアレ?と思ったことをついでに 書いておきます。問題になっているわけではないので、 Light Rubyist のつぶやきだと思って読み流してください。 ご教示いただいたように、以下のようにアクセッサ定義して 実験したら、確かに予想通りの結果が得られました。 class Class1 @@class_var1 = "c1" def self.class_var1 puts "GETTER" # for debug @@class_var1 end def self.class_var1=(v) puts "SETTER" # for debug @@class_var1 = v end end c = Class1.new c.instance_eval do p Class1.class_var1 Class1.class_var1 = "new c1" p Class1.class_var1 end # 実行結果 GETTER "c1" SETTER GETTER "new c1" Class1. とか、self.class. とか、メソッドの前にプレフィクスを つけなければならないのが面倒なので、インスタンスメソッドに 変更してみました。 class Class1 @@class_var1 = "c1" def class_var1 puts "GETTER" # for debug @@class_var1 end def class_var1=(v) puts "SETTER" # for debug @@class_var1 = v end end c = Class1.new c.instance_eval do p class_var1 class_var1 = "new c1" p class_var1 end # 実行結果 GETTER "c1" "new c1" インスタンスメソッドの場合とクラスメソッドの場合で、当然同じ結果が 得られるだろうと期待していましたが、そうではありませんでした。 実行コードをよく見れば、メソッド名(アクセッサ名)とローカル変数名が 衝突するからだということは分かりますが、少しだけ驚いたのでした。 アクセッサで何らかの前処理/後処理を行っている場合、インスタンス メソッド内でも、アクセッサの効果を期待して、つい上記のように 書いてしまいそうなので、気をつけなければなりませんね。 誰かの参考になればと思い、長々と書きました。 -- ひろひと