内部クラスから外部クラスのクラス変数を参照する

もち - 内部クラスと外部クラス
http://d.hatena.ne.jp/omochist/20061101/1162393034 より。

class_eval使って::Hogeクラスのコンテキストにしてやれば参照することができます。

元のサイトではインスタンス変数を使っていましたがやりたいこと的にはクラス変数を使う方が適切かなと思いました。

class Hoge
  def initialize
    @@x = "hoge"
    @fu = Fuga.new @@x
    @pi = Piyo.new @@x
    @ba = Bar.new @@x
  end

  def hoge
    @fu.hogera
    @pi.hogera
    @ba.hogera
    puts "hoge#{@@x}"
  end

  class Fuga
    def initialize x
        @@x = x
    end

    def hogera
      ::Hoge.class_eval %{ 
        puts @@x = "fuga" + @@x
      }
    end
  end

  class Piyo
    def initialize x
        @@x = x
    end

    def hogera
      ::Hoge.class_eval %{ 
        puts @@x = "piyo" + @@x
      }
    end
  end

  class Bar < ::Hoge
    def initialize x
      @@x = x
    end

    def hogera
      puts @@x = "bar#{@@x}"
    end
  end
end

とはいえ外部から他のクラスのインスタンス変数やクラス変数にアクセスする場合わかりづらくなるので親クラスなどにアクセサを定義してやってからアクセサ経由でアクセスした方がよいと思います。

ちなみに、BarのようにHogeと継承関係にある場合クラス変数は共有されるのでevalを使う必要はありません。

ここら辺の話はピッケル本よりもそろそろ第2版が出ると言われてるThe Ruby Wayが詳しくてオススメです。

The Ruby Way―Ruby道への招待

The Ruby Way―Ruby道への招待

Ruby Way, Second Edition, The: Solutions and Techniques in Ruby Programming (Addison-Wesley Professional Ruby Series)

Ruby Way, Second Edition, The: Solutions and Techniques in Ruby Programming (Addison-Wesley Professional Ruby Series)