Можно ли определить один 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? (в основном, я хочу, чтобы это было чистым, не-взломанным способом)
Ответы
Ответ 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