È possibile definire un metodo singleton Ruby usando un blocco?
-
02-07-2019 - |
Domanda
Quindi, voglio definire un metodo singleton per un oggetto, ma voglio farlo usando una chiusura.
Ad esempio,
def define_say(obj, msg)
def obj.say
puts msg
end
end
o = Object.new
define_say o, "hello world!"
o.say
Questo non funziona perché la definizione di un metodo singleton tramite " def " non è una chiusura, quindi ottengo un'eccezione che "msg" è una variabile o un metodo indefinito.
Quello che vorrei fare è qualcosa come usare il metodo " define_method " metodo nella classe Module, ma per quanto ne so, questo può essere usato solo per definire un metodo su una classe ... ma voglio un metodo Singleton ...
Quindi, mi piacerebbe scriverlo in questo modo:
def define_say(obj, msg)
obj.define_singleton_method(:say) {
puts msg
}
end
Qualcuno sa come posso raggiungere questo obiettivo senza dover creare un metodo per archiviare un Proc e quindi utilizzare Proc in un metodo singleton? (fondamentalmente, voglio un modo pulito e non confuso di farlo)
Soluzione
Ecco una risposta che fa quello che stai cercando
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
Utilizzo (incolla da IRB)
>> s = "my string"
=> "my string"
>> define_say(s, "I am S")
=> #<Proc:0xb6ed55b0@(irb):11>
>> s.say
I am S
=> nil
Per maggiori informazioni (e una piccola libreria che la rende meno disordinata) leggi questo:
http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html
A parte questo, se sei un programmatore di rubini e NON L'hai letto, vai a farlo ora ~!
Altri suggerimenti
Oggetto # define_singleton_method
è stato aggiunto a ruby-1.9.2 a proposito:
def define_say(obj, msg)
obj.define_singleton_method(:say) do
puts msg
end
end