2008-09-25 12 views
11

तो, मैं किसी ऑब्जेक्ट के लिए सिंगलटन विधि को परिभाषित करना चाहता हूं, लेकिन मैं इसे बंद करने का उपयोग करना चाहता हूं।क्या ब्लॉक का उपयोग कर रूबी सिंगलटन विधि को परिभाषित करना संभव है?

उदाहरण के लिए,

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

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

इसका कारण यह है "def" के माध्यम से एक सिंगलटन विधि को परिभाषित करने के लिए एक बंद नहीं है काम नहीं करता है, तो मैं एक अपवाद है कि "संदेश" एक अपरिभाषित चर या विधि है मिलता है।

मैं जो करना चाहता हूं वह मॉड्यूल क्लास में "define_method" विधि का उपयोग करने जैसा कुछ है, लेकिन जहां तक ​​मैं कह सकता हूं, इसका उपयोग केवल कक्षा पर एक विधि को परिभाषित करने के लिए किया जा सकता है ... लेकिन मैं चाहता हूं एक सिंगलटन विधि ...

तो, मैं यह कुछ इस तरह लिखने के लिए प्यार होता है: एक प्रोक की दुकान और फिर उपयोग करने के लिए एक विधि बनाए बिना

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

क्या किसी को पता है कि मैं यह कैसे प्राप्त कर सकते हैं एक सिंगलटन विधि के भीतर प्रक्रिया? (मूल रूप से, मैं एक साफ, ऐसा करने का गैर hacky रास्ता चाहते हैं)

उत्तर

8

यहाँ एक जवाब है जो आप के लिए

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 

प्रयोग जो खोज रहे हैं (आईआरबी से पेस्ट)

>> 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

एक तरफ के रूप में, यदि आप एक रूबी प्रोग्रामर हैं, और आपने इसे पढ़ा नहीं है, तो अब इसे करें ~!

+0

प्रतिभाशाली! अच्छी तरह से काम! धन्यवाद टन! –

+0

मैंने लिंक बदल दिया, क्योंकि इस जवाब को पोस्ट करने के बाद से AWOL क्यों गया था। –

संबंधित मुद्दे

 संबंधित मुद्दे