आप कैसे डिफाइनमेंट पास करते हैं define_method?


155

मैं एक तर्क (ओं) को एक विधि को पारित करना चाहूंगा, जिसे define_method का उपयोग करके परिभाषित किया जाएगा, मैं यह कैसे करूंगा?

जवाबों:


198

जिस ब्लॉक को आप define_method में पास करते हैं, उसमें कुछ पैरामीटर शामिल हो सकते हैं। इस तरह आपकी परिभाषित पद्धति तर्कों को स्वीकार करती है। जब आप एक विधि को परिभाषित करते हैं तो आप वास्तव में केवल ब्लॉक को निनामन करते हैं और कक्षा में इसका संदर्भ रखते हैं। पैरामीटर ब्लॉक के साथ आते हैं। इसलिए:

define_method(:say_hi) { |other| puts "Hi, " + other }

खैर यह सिर्फ सरासर अनाड़ी की बात है। अच्छा काम, केविन कॉस्टनर।
डार्थ एलीगियस

90

... और यदि आप वैकल्पिक पैरामीटर चाहते हैं

 class Bar
   define_method(:foo) do |arg=nil|                  
     arg                                                                                          
   end   
 end

 a = Bar.new
 a.foo
 #=> nil
 a.foo 1
 # => 1

... जितने चाहे उतने तर्क

 class Bar
   define_method(:foo) do |*arg|                  
     arg                                                                                          
   end   
 end

 a = Bar.new
 a.foo
 #=> []
 a.foo 1
 # => [1]
 a.foo 1, 2 , 'AAA'
 # => [1, 2, 'AAA']

...का संयोजन

 class Bar
   define_method(:foo) do |bubla,*arg|
     p bubla                  
     p arg                                                                                          
   end   
 end

 a = Bar.new
 a.foo
 #=> wrong number of arguments (0 for 1)
 a.foo 1
 # 1
 # []

 a.foo 1, 2 ,3 ,4
 # 1
 # [2,3,4]

... उन सभी को

 class Bar
   define_method(:foo) do |variable1, variable2,*arg, &block|  
     p  variable1     
     p  variable2
     p  arg
     p  block.inspect                                                                              
   end   
 end
 a = Bar.new      
 a.foo :one, 'two', :three, 4, 5 do
   'six'
 end

अपडेट करें

रूबी 2.0 ने डबल स्पैट **(दो स्टार) पेश किए, जो ( मैं बोली ) करता है:

रूबी 2.0 ने खोजशब्द तर्क प्रस्तुत किए, और ** कार्य * की तरह, लेकिन खोजशब्द तर्क के लिए। यह कुंजी / मान जोड़े के साथ एक हैश लौटाता है।

... और निश्चित रूप से आप इसे परिभाषित विधि में भी उपयोग कर सकते हैं :)

 class Bar 
   define_method(:foo) do |variable1, variable2,*arg,**options, &block|
     p  variable1
     p  variable2
     p  arg
     p  options
     p  block.inspect
   end 
 end 
 a = Bar.new
 a.foo :one, 'two', :three, 4, 5, ruby: 'is awesome', foo: :bar do
   'six'
 end
# :one
# "two"
# [:three, 4, 5]
# {:ruby=>"is awesome", :foo=>:bar}

नामित विशेषताएँ उदाहरण:

 class Bar
   define_method(:foo) do |variable1, color: 'blue', **other_options, &block|
     p  variable1
     p  color
     p  other_options
     p  block.inspect
   end
 end
 a = Bar.new
 a.foo :one, color: 'red', ruby: 'is awesome', foo: :bar do
   'six'
 end
# :one
# "red"
# {:ruby=>"is awesome", :foo=>:bar}

मैं सभी में एक साथ कीवर्ड तर्क, बवंडर और डबल स्पैट के साथ उदाहरण बनाने की कोशिश कर रहा था:

 define_method(:foo) do |variable1, variable2,*arg, i_will_not: 'work', **options, &block|
    # ...

या

 define_method(:foo) do |variable1, variable2, i_will_not: 'work', *arg, **options, &block|
    # ...

... लेकिन यह काम नहीं करेगा, ऐसा लगता है कि एक सीमा है। जब आप इसके बारे में सोचते हैं तो यह समझ में आता है कि स्पैट ऑपरेटर "सभी शेष तर्कों को कैप्चर कर रहा है" और डबल स्पैट "सभी शेष तर्कों को कैप्चर कर रहा है" इसलिए उन्हें मिश्रण करना अपेक्षित तर्क को तोड़ देगा। (मेरे पास इस बिंदु को साबित करने के लिए कोई संदर्भ नहीं है!)

अपडेट 2018 अगस्त:

सारांश लेख: https://blog.eq8.eu/til/metaprogramming-ruby-examples.html


दिलचस्प - 4 वें ब्लॉक को विशेष: इसने 1.8.7 पर काम किया! पहले ब्लॉक ने 1.8.7 में काम नहीं किया, और दूसरे ब्लॉक में एक टाइपो ( a.foo 1इसके बजाय होना चाहिए foo 1) है। धन्यवाद!
सोनी संतोस

1
प्रतिक्रिया के लिए धन्यवाद, टाइपो तय किया गया था, ... माणिक 1.9.3 और 1.9.2 पर सभी उदाहरण काम करते हैं और मैं सकारात्मक हूँ कि 1.9.1 पर भी (लेकिन कोशिश नहीं की)
समतुल्य

मैंने इस उत्तर को stackoverflow.com/questions/4470108/… पर स्वीकृत उत्तर के साथ जोड़ दिया है ताकि यह पता लगाया जा सके कि रनगेट पर एक विधि को कैसे अधिलेखित किया जा सकता है (वैकल्पिक ओवरगेट) और ब्लॉक लेता है और फिर भी ऑर्गन्स के साथ मूल विधि को कॉल करने में सक्षम है। और ब्लॉक करें। आह, माणिक। विशेष रूप से, मुझे Savon को अधिलेखित करने की आवश्यकता है :: एक होस्ट के लिए एक एकल एपीआई कॉल के लिए मेरे देव एनवी में क्लाइंट.रेक्वेस्ट मैं केवल उत्पादन में उपयोग कर सकता हूं। चीयर्स!
pduey

59

केविन कोनर के जवाब के अलावा: ब्लॉक तर्क पद्धति के तर्कों के समान शब्दार्थ का समर्थन नहीं करते हैं। आप डिफ़ॉल्ट तर्क या ब्लॉक तर्क को परिभाषित नहीं कर सकते।

यह केवल रूबी 1.9 में नए वैकल्पिक "स्टैबी लैम्ब्डा" सिंटैक्स के साथ तय किया गया है जो पूर्ण विधि तर्क शब्दार्थ का समर्थन करता है।

उदाहरण:

# Works
def meth(default = :foo, *splat, &block) puts 'Bar'; end

# Doesn't work
define_method :meth { |default = :foo, *splat, &block| puts 'Bar' }

# This works in Ruby 1.9 (modulo typos, I don't actually have it installed)
define_method :meth, ->(default = :foo, *splat, &block) { puts 'Bar' }

3
वास्तव में, मेरा मानना ​​है कि डिफेंड_मिथोड पर तर्कों का समर्थन स्पलैट करते हैं, जो डिफ़ॉल्ट तर्कों को भी परिभाषित करने के लिए एक दौर-ए-बाउट तरीका प्रदान कर सकता है।
चिनसौर

1
चिनसौर ब्लॉक तर्कों के बारे में सही है, जिसमें छप की अनुमति है। मैंने रूबी 1.8.7 और 1.9.1 दोनों में इसकी पुष्टि की है।
पीटर वैगेनेट

धन्यवाद, मैं इस बारे में भूल गया। अब तय हो गया।
जोर्ग डब्ल्यू मित्तग

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.