私が「送信」方法を理解している限り、これは
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
ただし、パブリックメソッドのみを呼び出すことができるようにするために使用できます。
In addition to Intrepidd's use cases, it is convenient when you want to route different methods on the same receiver and/or arguments. If you have some_object
, and want to do different things on it depending on what foo
is, then without send
, you need to write like:
case foo
when blah_blah then some_object.do_this(*some_arguments)
when whatever then some_object.do_that(*some_arguments)
...
end
but if you have send
, you can write
next_method =
case foo
when blah_blah then :do_this
when whatever then :do_that
....
end
some_object.send(next_method, *some_arguments)
or
some_object.send(
case foo
when blah_blah then :do_this
when whatever then :do_that
....
end,
*some_arguments
)
or by using a hash, even this:
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に保つのに役立つことがあります。これは非常に特殊なケースですが、有効なケースだと思います。
同僚がすでに言ったことを簡単に要約すると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)