[ruby-list:47026] Re: [Q] instance_eval 中でのクラス変数のアクセス

From: swec@...
Date: 2010-04-17 07:07:16 UTC
List: ruby-list #47026
東(質問者)です。

> クラス変数を外部から自由に扱いたい(+それでかまわ
> ない)というのであるなら、クラス変数へのアクセサを
> 定義するのが吉。

たしかに、そうですね。

最初の検証プログラムでも、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"


インスタンスメソッドの場合とクラスメソッドの場合で、当然同じ結果が
得られるだろうと期待していましたが、そうではありませんでした。
実行コードをよく見れば、メソッド名(アクセッサ名)とローカル変数名が
衝突するからだということは分かりますが、少しだけ驚いたのでした。

アクセッサで何らかの前処理/後処理を行っている場合、インスタンス
メソッド内でも、アクセッサの効果を期待して、つい上記のように
書いてしまいそうなので、気をつけなければなりませんね。

誰かの参考になればと思い、長々と書きました。

-- 
ひろひと

In This Thread

Prev Next