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

时间:2013-02-09 23:58:12

标签: ruby methods send

据我所知'发送'方法,这个

some_object.some_method("im an argument")

与此相同

some_object.send :some_method, "im an argument"

那么使用'send'方法有什么意义?

5 个答案:

答案 0 :(得分:18)

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

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

send

您可以使用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 但只能调用公共方法。

答案 1 :(得分:5)

除了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)

答案 2 :(得分:4)

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

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代码和模板干。这是一个非常具体的案例,但我认为它是有效的案例。

答案 3 :(得分:0)

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

class Validator
  def name
    'Mozart'
  end
  def location
    'Salzburg'
  end
end

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

答案 4 :(得分:-1)

我喜欢这种建筑

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