据我了解“发送”方法,这使用“发送”而不是普通方法调用的要点是什么?
some_object.some_method("im an argument")
是相同的,因为这
some_object.send :some_method, "im an argument"
那么,什么是使用“发送”方法呢?
据我了解“发送”方法,这使用“发送”而不是普通方法调用的要点是什么?
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
,但只能调用公共方法。
第二个用例远比第一个更重要,IMO。 – 2013-02-10 00:45:15
如果您的唯一意图是动态调用,则可以使用'public_send'。 – 2013-02-10 02:41:44
使用send不是一个不好的做法。 – christianblais 2013-02-10 06:43:58
除了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)
简要总结了同事已经说过的内容: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)
除了别人的答案,一个良好的用例是通过方法迭代包含一个递增数字。
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代码和模板干爽。这是一个非常具体的案例,但我认为这是一个有效的案例。
我会说任何取决于增加数字的命名都是严重的代码异味。上面的类可能需要像def属性这样的方法; [“foo”,“bar”,“baz”]; end'。 – 2016-01-22 12:23:08
你说得对。当时我是个白痴。但显然,发送仍然有其作为元编程工具的地位。 – Ravenstine 2016-01-22 16:54:10
要清楚:我从来没有称你为白痴,也不认为你是一个白痴。你的'send'的例子是完全有效的,但希望额外的洞察力可以用于没有经验的未来读者。 – 2016-01-22 16:56:38
因为'send'的参数是一个符号,可以保存在一个变量中。例如,'foo =:size; [] .send foo'。虽然它可以用于访问私有方法,但IMO将其作为通用消息传递工具的用途远远超过其作为“围绕”开发人员意图的方式的价值。 – 2013-02-10 00:47:49