metodos - ¿Es posible definir un método singleton de Ruby usando un bloque?
metodos en ruby (2)
Entonces, quiero definir un método singleton para un objeto, pero quiero hacerlo usando un cierre.
Por ejemplo,
def define_say(obj, msg)
def obj.say
puts msg
end
end
o = Object.new
define_say o, "hello world!"
o.say
Esto no funciona porque la definición de un método singleton a través de "def" no es un cierre, por lo que me sale una excepción que "msg" es una variable o método indefinido.
Lo que me gustaría hacer es algo así como usar el método "define_method" en la clase Module, pero hasta donde puedo decir, esto solo se puede usar para definir un método en una clase ... pero quiero un Método Singleton. ..
Entonces, me encantaría escribir algo como esto:
def define_say(obj, msg)
obj.define_singleton_method(:say) {
puts msg
}
end
¿Alguien sabe cómo puedo lograr esto sin tener que crear un método para almacenar un Proc y luego usar el Proc dentro de un método singleton? (Básicamente, quiero una forma limpia y no hacky de hacer esto)
Aquí hay una respuesta que hace lo que estás buscando
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
Uso (pegar desde IRB)
>> s = "my string"
=> "my string"
>> define_say(s, "I am S")
=> #<Proc:0xb6ed55b0@(irb):11>
>> s.say
I am S
=> nil
Para obtener más información (y una pequeña biblioteca que lo hace menos complicado), lea esto:
http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html
Por otro lado, si eres un programador de rubíes, y NO HAS LEÍDO, ¡hazlo ahora ~!
Object#define_singleton_method
fue agregado a ruby-1.9.2 por cierto:
def define_say(obj, msg)
obj.define_singleton_method(:say) do
puts msg
end
end