2008-09-25 2 views
11

Also möchte ich eine Singleton-Methode für ein Objekt definieren, aber ich möchte es mit einer Schließung machen.Ist es möglich, eine Ruby-Singleton-Methode mit einem Block zu definieren?

Zum Beispiel

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

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

Das funktioniert nicht, weil über „def“, um eine Singleton-Methode definiert, keinen Verschluss, so dass ich eine Ausnahme, dass „msg“ ist ein nicht definierte Variable oder Methode.

Was ich gerne tun würde ist so etwas wie die "define_method" -Methode in der Modul-Klasse, aber so weit ich sagen kann, kann dies nur verwendet werden, um eine Methode auf einer Klasse zu definieren ... aber ich will eine Singleton-Methode ...

Also, ich würde es lieben so etwas zu schreiben:

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

Wer weiß, wie ich das erreichen kann, ohne ein Verfahren zur Herstellung eines Proc speichern erstellen zu müssen und dann verwenden der Proc in einer Singleton-Methode? (Im Grunde möchte ich einen sauberen, nicht-hacky Weg, dies zu tun)

Antwort

8

Hier ist eine Antwort, die tut, was Sie für

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 

Usage (Paste aus IRB) suchen

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

Für weitere Informationen (und eine kleine Bibliothek, die es weniger chaotisch macht) lesen sie:

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

Als beiseite, wenn Sie ein Ruby-Programmierer sind, und Sie haben nicht gelesen, gehen Sie es jetzt tun ~!

+0

brilliant! Funktioniert perfekt! Vielen Dank! –

+0

Ich habe den Link geändert, weil _why AWOL ging, seit diese Antwort gepostet wurde. –

Verwandte Themen