内部クラスと外部クラスの解

id:omochist:20061101:1162393034
まさか反響があるとは思わなかった.なんせ,ただ疑問に思った事を羅列しただけなんだもの.順番に,ソースコードを眺めます.

id:OTTiiさんの解

コメントにて解をいただきました.この解は,

共有したい変数を持つ内部クラスを作って,その変数のアクセサを定義して内部クラスと外部クラスで値を共有しよう

っていう代物.なるほど,確かにこれなら確実な気もしますが,なんでこれはValクラスが参照渡しになるんでしょうか.Stringクラスだってそのまま参照渡ししてくれれば良いのになぁ.この辺は,なんというかコンストラクタが明確に存在するJavaが羨ましい.

id:walf443さんの解

こちらは,トラックバックにて解をいただきました.
id:walf443:20061102:1162436996
この解は,

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

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

という代物.こんな手法もあるんですね.class_eval自体初めて見ましたよ.
これは,FugaやPiyoの中でHogeの中身を呼んでevalって感じでしょうかね.なるほど,それなら確かにクラス変数じゃないとダメっぽい.


で,ふと思ったのですが

Hoge.class_eval %{ … }

じゃなくて,わざわざ

::Hoge.class_eval %{ … }

って書いているのは,id:walf443さんの美学だったりするのかしら.美学重要よね.


さらに,class_evalを使うのならinitializeで@@xは渡さなくてもいけますね(FugaとPiyo).このほうがスッキリして良いかも.あと,内部クラスで外部クラスを継承してクラス変数を共有する形にすると,別に内部クラスである必要がなくなって悲しい気も.


さらに,参考となる本も紹介してくださった.

The Ruby Way―Ruby道への招待

The Ruby Way―Ruby道への招待

Amazon価格5040円…研究室で買ってもらおう.うん.

ありがとうございます

わざわざヘンテコな疑問に乗って頂いて,ありがとうございます.ただやっぱり,スッキリとしたものが無いんだよなぁ.「やりようによってはできる」とわかっただけでも大収穫なのですが.

そこで

Valは参照渡しだけれどStringは複製渡しであると言う事を考慮して,気持ち悪い解法を考えてみた.

class Hoge
  def initialize
    @x = "hoge"
    @p = proc { |str| @x = str + @x }
    @fu = Fuga.new(@p)
    @pi = Piyo.new(@p)
  end
  
  def hoge
    @fu.hogera
    @pi.hogera
    puts "hoge" + @x
  end
  
  class Fuga
    def initialize(p)
      @p = p
    end
    
    def hogera
      puts @p.call("fuga")
    end
  end
  
  class Piyo
    def initialize(p)
      @p = p
    end
    
    def hogera
      puts @p.call("piyo")
    end
  end
end

Hoge.new.hoge

なんとも拡張性がありませんね.クロージャだから値は保持されるし,ちゃんと結果は返るんですけど….もうちょっと真面目になるべきだね.