Что эквивалентно «ссылке на метод» в Ruby

21

например, в python можно присвоить метод переменной:

class MyClass 
    def myMethod(self):
        return "Hi"


 x = MyClass()
 method = x.myMethod

 print method() # prints Hi

Я знаю, что это должно быть возможно в Ruby, но я не знаю, каков синтаксис.

    
задан OscarRyz 20.04.2010 в 21:00
источник

2 ответа

28

Вам нужно получить метод, используя method с именем метода в качестве аргумента. Это вернет вам экземпляр типа Method , который можно вызвать с помощью call() .

class MyClass
  def myMethod
    "Hi"
  end
end

x = MyClass.new
m = x.method(:myMethod)
# => #<Method: MyClass#myMethod>

puts m.call
# You can also do m[] instead of m.call()

Обратите внимание, что любые аргументы необходимо добавить в метод call .

Однако во многих практических случаях нет необходимости сохранять сам метод в переменной в Ruby; если вы просто хотите динамически вызывать метод (то есть отправлять сообщение объекту) и нет необходимости сохранять метод, вы также можете использовать метод send (или __send__ в случае конфликта имен).

x = MyClass.new
puts x.send :myMethod # also possible with a string: m.send "myMethod"
# "Hi"

Любые аргументы должны следовать за именем метода:

puts x.send(:myMethod, arg1, arg2)

Использовать его таким образом, вероятно, больше похоже на Ruby, поскольку концепция классов метода не так заметна, как в Python. В Python вы всегда можете подумать о двухступенчатом механизме, когда выполняете что-то вроде a_string.split() ; сначала вы получаете метод с помощью a_string.split , а затем вызываете его (либо неявно с () , либо явно с __call__() ). Таким образом, разрезание этого двухступенчатого механизма вполне закономерно.

Ruby больше основан на передаче сообщений, и чтобы получить класс метода в Ruby, вам придется проделать дополнительную работу, потому что в некотором смысле объект метода должен быть создан для вас на этом этапе. Поэтому, если вам действительно не нужен какой-либо объект Methods в Ruby, вам следует придерживаться абстракции передачи сообщений и просто использовать send .

    
ответ дан Debilski 20.04.2010 в 21:05
  • Хороший ответ. Но разве это не x.send, а не m.send? –  FMc 21.04.2010 в 01:04
  • Да, вы правы. m в этом сценарии даже не будет определено. –  Debilski 21.04.2010 в 01:54
  • Обратите внимание, что метод () будет возвращать новый объект с каждым вызовом, а не что-то важное большую часть времени, но иногда может быть получено, например. в тестах. –  David Moles 28.03.2016 в 20:09
4

Я думаю, что вы ищете Proc или лямбда-блок

x = Proc.new { return "Hello World" }
puts x.call

x = lambda { return "Hello World" }
puts x.call

Я бы прочитал этот короткий пост - есть небольшое, но существенное различие в поведении методов Ссылка

    
ответ дан house9 20.04.2010 в 21:08
  • Нет, на самом деле это не то, что я нашел на большинстве сайтов в Интернете, но не совсем то, что искал, в любом случае, спасибо. –  OscarRyz 20.04.2010 в 21:11
  • Функциональный способ делать вещи! Я предпочитаю этот ответ –  metrix 01.12.2014 в 23:41