使用“发送”而不是普通的方法调用有什么意义?

据我了解’发送’方法,这个

some_object.some_method("im an argument") 

与此相同

 some_object.send :some_method, "im an argument" 

那么使用’发送’方法有什么意义呢?

如果您事先不知道方法的名称,它可以派上用场,例如,当您进行元编程时,您可以在变量中使用方法的名称并将其传递给send方法。

它也可以用于调用私有方法,尽管大多数Ruby开发人员认为这种特殊用法并不是一种好习惯。

 class Test private def my_private_method puts "Yay" end end t = Test.new t.my_private_method # Error t.send :my_private_method #Ok 

您可以使用public_send但只能调用公共方法。

除了Intrepidd的用例之外,当您想要在同一个接收器和/或参数上路由不同的方法时,这很方便。 如果你有some_object ,并希望根据foo不同做什么,那么没有send ,你需要写如下:

 case foo when blah_blah then some_object.do_this(*some_arguments) when whatever then some_object.do_that(*some_arguments) ... end 

但如果你有send ,你可以写

 next_method = case foo when blah_blah then :do_this when whatever then :do_that .... end some_object.send(next_method, *some_arguments) 

要么

 some_object.send( case foo when blah_blah then :do_this when whatever then :do_that .... end, *some_arguments ) 

或者使用哈希,即使这样:

 NextMethod = {blah_blah: :do_this, whatever: :do_that, ...} some_object.send(NextMethod[:foo], *some_arguments) 

除了其他人的答案之外,一个好的用例是迭代包含递增数字的方法。

 class Something def attribute_0 "foo" end def attribute_1 "bar" end def attribute_2 "baz" end end thing = Something.new 3.times do |x| puts thing.send("attribute_#{x}") end #=> foo # bar # baz 

这可能看起来微不足道,但它偶尔帮助我保持我的Rails代码和模板干。 这是一个非常具体的案例,但我认为这是一个有效的案例。

简要总结了同事已经说过的内容: send方法是元编程的语法糖。 下面的示例演示了可能无法对方法进行本机调用的情况:

 class Validator def name 'Mozart' end def location 'Salzburg' end end v = Validator.new '%name% was born in %location%'.gsub (/%(?\w+)%/) do # v.send :"#{Regexp.last_match[:mthd]}" v.send Regexp.last_match[:mthd].to_sym end => "Mozart was born in Salzburg" 

我喜欢这种建筑

 Object.get_const("Foo").send(:bar)