就我理解的“send”方法而言,这个
some_object.some_method("im an argument")
与此相同
some_object.send :some_method, "im an argument"
那么使用“send”方法的重点是什么?
如果您不事先知道方法的名称,当您进行元编程时,可以将方法名称存储在变量中并传递给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
,只能调用公共方法。
public_send
。 - Andrew Marshallsend
非常方便。如果您有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代码和模板DRY。这是一个非常特定的情况,但我认为它是有效的。
def attributes; ["foo", "bar", "baz"]; end
这样的方法。 - Jezen Thomasclass 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)
send
方法的参数是一个符号,可以保存在变量中。例如:foo = :size; [].send foo
。虽然它可以用于访问私有方法,但我认为它作为一种通用消息传递工具的价值远远超过了作为绕过开发者意图的方式。 - Dave Newton