据我了解“发送”方法,这个
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 (/%(?<mthd>\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)