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

Можно ли определить один Singleton-метод Ruby с использованием блока?

Итак, я хочу определить метод singleton для объекта, но я хочу сделать это с помощью закрытия.

Например,

def define_say(obj, msg)
  def obj.say
    puts msg
  end
end

o = Object.new
define_say o, "hello world!"
o.say

Это не работает, потому что определение метода singleton через "def" не является закрытием, поэтому я получаю исключение, которое "msg" является переменной или методом undefined.

То, что я хотел бы сделать, - это что-то вроде использования метода define_method в классе Module, но, насколько я могу судить, это можно использовать только для определения метода в классе... но я хочу, чтобы Метод Singleton...

Итак, я хотел бы написать что-то вроде этого:

def define_say(obj, msg)
  obj.define_singleton_method(:say) {
    puts msg
  }
end

Кто-нибудь знает, как я могу достичь этого, не создавая метод для хранения Proc, а затем использовать Proc в методе singleton? (в основном, я хочу, чтобы это было чистым, не-взломанным способом)

4b9b3361

Ответ 1

Вот ответ, который делает то, что вы ищете

def define_say(obj, msg)
  # Get a handle to the singleton class of obj
  metaclass = class << obj; self; end 

  # add the method using define_method instead of def x.say so we can use a closure
  metaclass.send :define_method, :say do
    puts msg
  end
end

Использование (вставка из IRB)

>> s = "my string"
=> "my string"
>> define_say(s, "I am S")
=> #<Proc:[email protected](irb):11>
>> s.say
I am S
=> nil

Для получения дополнительной информации (и небольшой библиотеки, которая делает ее менее беспорядочной), прочитайте следующее:

http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html

Как в стороне, Если вы рубиновый программист, и вы НЕ читали это, сделайте это сейчас ~!

Ответ 2

Object#define_singleton_method был добавлен к ruby-1.9.2, кстати:

def define_say(obj, msg)
  obj.define_singleton_method(:say) do
    puts msg
  end
end