Подтвердить что ты не робот

Какой смысл использовать "отправить" вместо обычного вызова метода?

Насколько я понимаю метод отправки, этот

some_object.some_method("im an argument")

совпадает с этим

some_object.send :some_method, "im an argument"

Итак, какова точка, использующая метод "Отправить"?

4b9b3361

Ответ 1

Это может пригодиться, если вы не знаете заранее имя метода, например, когда вы выполняете метапрограммирование, вы можете иметь имя метода в переменной и передать его в 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, но только для вызова общедоступных методов.

Ответ 2

В дополнение к случаям использования 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)

Ответ 3

В дополнение ко всем остальным ответам, хороший пример использования будет для итерации с помощью методов, содержащих инкрементирующую цифру.

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. Это очень конкретный случай, но я считаю его действительным.

Ответ 4

Суммируя кратко то, что уже было сказано коллегами: 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" 

Ответ 5

Мне нравится эта конструкция

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