2013-02-09 6 views
12

方法を「送信」、この通常のメソッド呼び出しの代わりに "send"を使用する点は何ですか?私の知る限り理解し

some_object.some_method("im an argument") 

この

some_object.send :some_method, "im an argument" 

と同じであるので、「送信」メソッドを使用してポイントは何ですか?

+0

'send'のパラメータはシンボルであり、変数に保持することができます。例えば、 'foo =:size; [] .send foo'。 IMOはプライベートメソッドにアクセスするために使用できますが、一般的なメッセージングツールとしてのIMOの使用は、開発者の意図を「包囲」する方法としての価値よりはるかに優れています。 –

答えて

16

メソッドの名前をあらかじめ知っていないと便利です。たとえばメタプログラミングをしているときに、メソッドの名前を変数に入れて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でも公開メソッドを呼び出すことができます。

+8

2番目のユースケースは、最初のIMOよりもはるかに重要です。 –

+4

あなたの唯一の意図が動的に呼び出すことであるなら 'public_send'を使うことができます。 –

+0

sendを使うのは悪いことではありません。 – christianblais

5

Intrepiddの使用例に加えて、同じ受信者および/または引数で異なるメソッドをルーティングする場合に便利です。

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を持っており、どのような fooに応じて、その上で異なることをしたい場合は、 sendせずに、あなたは次のように記述する必要がありますされ

または

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) 
0

すでにまとめられているのは、同僚がすでに言ったことです。sendメソッドは、メタプログラミングのためのシンタックスシュガーです。私は皆の答えに加えて

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

:以下の例では、メソッドへのネイティブ呼び出しはおそらく不可能な場合を示しています増分する桁を含む。

これは些細なことかもしれませんが、時折RailsコードとテンプレートDRYを保持するのに役立ちます。それは非常に特殊なケースですが、私はそれが有効なものだと思います。

4

は、良いユースケースは、メソッドを反復処理のためになるこのcostructionに好き

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" 
+0

数字の増分に依存する命名は深刻なコード臭です。上記のクラスはおそらく 'def属性のようなメソッドを必要とします。 ["foo"、 "bar"、 "baz"];終わり。 –

+0

あなたは正しいです。私はその当時の馬鹿だった。しかしsendはまだ明らかにメタプログラミングツールとしての地位を持っています。 – Ravenstine

+0

明確にする:決して私はあなたを馬鹿と呼んでいませんでした。あなたの 'send'の例は完全に有効ですが、経験の豊富な将来の読者には余分な洞察が役立ちます。 –

関連する問題