0

私は次のように何かを書いています

module Test
   def self.print(*args)
      p 'something'
      p args
   end
end

def print(*args)
  p "print something"
  p args
end

def method_caller(method_name, *args)
  send(method_name, *args)
end

method_caller(:print, 2) # this works fine
method_caller("print", 2, 3) # this one also
method_caller("Test.print", 2) # this doesn't work

基本的にmethod_caller、メソッドの名前といくつかの引数を渡し、そのsendメソッドを使用して実際にメソッドを呼び出します。

私は通常、メソッドの名前をシンボルとして渡しますが、どのように処理しTest.printますか?ある時点で、オブジェクトを渡して、オブジェクトに独自のメソッドを呼び出させる可能性があると思います。

私が呼び出したいメソッドは、文字通りどこでもかまいません。

アップデート:

それぞれの提案を試してみると、何が起こっているのかは明らかなので、明示的な受信者はそれを行うのに良い方法のように見えますが、クリスチャンブレアの考えはどうでしょうか。evalそのような呼び出しを避けるためにそれを変更しました

def method_caller(method_name, *args)
  if method_name.is_a?(String)
    chain = method_name.split('.')
    obj, method_name = Object.const_get(chain[0...-1].join('.')), chain[-1]
    obj.send(method_name, *args)
  else
    send(method_name, args)
  end
end

つまり、私はただ言うことができますmethod_caller("Test.print", 2)が、おそらくいくつかの落とし穴があります...

4

3 に答える 3

1

ここには2つのことがあります。

1)メソッド定義が引数を受け入れないときに引数を指定してTest.printを呼び出そうとしているため、例は機能しません。 編集:ちょうどあなたの更新を見ました。今は大丈夫です。ごめん!

2)それは悪いことですが、いつでも次のようにevalを使用できます:

module Test
   def self.print(*args)
     p 'something'
     p args
   end
end

def method_caller(method_name, *args)
  if method_name.is_a?(String)
    chain = method_name.split('.')
    eval(chain[0...-1].join('.')).send(chain.last, args)
  else
    send(method_name, args)
  end
end

method_caller(:print, 2) # this works fine
method_caller("print", 2, 3) # this one also
method_caller("Test.print", 2) # this doesn't work
于 2012-08-16T20:26:29.847 に答える
1

では、method_caller にレシーバー引数を与えてみませんか?

def method_caller(receiver, method_name, *args)
  receiver.send(method_name, *args)
end

method_caller(Test, :print, 2)

他の呼び出しselfはレシーバーとして使用する必要がありますが、これは現在の実装では暗黙的です。しかし、最終的にこれで得られるのは の不完全なアドホックな再実装ですsend

于 2012-08-16T20:27:37.430 に答える
0

文字列として呼び出すメソッドを渡すことは要件ですか、それとも単なるアイデアですか? よりルビーっぽい解決策は、単にブロックを渡すことです...

method_caller(2) { |*args| Object.print(*args) }

または、メソッドオブジェクトを引数として与える

method_caller(Object.method(:print), 2)

ところで、これは #call (labmdas など) に応答するすべてのオブジェクトで機能します。

于 2012-08-17T14:23:42.430 に答える