我写的内容如下
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
?我想在某些时候我可能会传递对象并让他们调用自己的方法。
我想调用的方法可以在任何地方。
更新:
尝试每个建议,明确的接收器看起来是一个好方法,因为它很明显发生了什么,但是Christianblais的想法呢。我更改了它以避免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)
,但也许有一些陷阱......
答案 0 :(得分:1)
这里有两件事。
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
答案 1 :(得分:1)
那么,为什么不给你的method_caller一个接收器参数?
def method_caller(receiver, method_name, *args)
receiver.send(method_name, *args)
end
method_caller(Test, :print, 2)
其他调用需要使用self
作为接收器,这在您当前的实现中是隐含的。但最后所有这些都是send
的一个不完整的临时重新实现,所以人们真的很想知道你想要实现的目标。
答案 2 :(得分:0)
传递方法作为字符串调用是一个要求还是只是一个想法?一个更为红宝石的解决方案就是简单地传递一个块...
method_caller(2) { |*args| Object.print(*args) }
或者将方法对象作为参数
method_caller(Object.method(:print), 2)
顺便说一下,哪个对象响应#call(labmdas,...)