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

18

Например, в 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 ответа

25

Вам нужно захватить метод, используя 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