3

文字列(メソッド名)とブロック(メソッドの内容)からRubyでインスタンスメソッドを定義することは可能ですか?

これには instance_eval() を使用する必要があると思いますが、2 つのデータ型を混在させる方法はまだわかりません。文字列とブロックの両方が動的に決定されるため、先頭に「def #{string}」を付けてブロックを作成すると機能します-これを行う方法がわかりません。

私のユース ケースは、Bacula 構成ファイルを表すクラスです。構成ファイルには、さまざまな種類のリソースを含めることができます。それらはすべて、舞台裏で比較的複雑なデータ構造に格納されています (他の理由により、この構造を単純化しても、私が探しているものを達成することはできません)。名前付きメソッドを介してリソースにすばやくアクセスできるようにしたいと考えています。

たとえば、A は 1 つの構成ファイルを表し、B は別の構成ファイルを表します。A にはリソース Director、Client、Job があり、B には Messages と Director があります。

この場合、A にはメソッド director()、client()、および job() が必要であり、B には messages() および director() があります。これらのそれぞれは、オブジェクトのそれぞれの構成ファイルから関連するリソースを返します。

これを行うためのより簡単な方法 ([] メソッドの実装など) があることは知っていますが、現時点では、好奇心のためにより難しい解決策を追求しています。

4

1 に答える 1

4

あなたが探しているのはdefine_methodモジュールのメソッドだと思います。ただし、それは非公開であるため、class_eval実行するには何かを使用する必要があります。

body = proc { self * 3 }
name = "triple"
c = Numeric

c.class_eval { define_method(name.to_sym, &body) }

3.triple # 9

そして、引数を持つメソッド:

body = proc { |second| [self * 3, second * 3] }
name = "triple_both"
c = Numeric

c.class_eval { define_method(name.to_sym, &body) }

puts 3.triple_both(5) # [9, 15]

シングルトンオブジェクト(またはEigenclass、またはそれらが呼び出されたもの)に新しいメソッドを配置するには:

body = proc { puts @meme + @meme + @meme }
name = "meme"
class SwedishChef; def initialize; @meme = "bork"; end; end    
sc = SwedishChef.new
(class << sc; self; end).class_eval { 
  define_method(name.to_sym, &body)
}
sc.meme # borkborkbork

[編集 (Jörg W Mittag): シングルトン メソッドの例を修正しました。]

于 2009-07-10T15:54:08.203 に答える