2008-09-18 12 views

उत्तर

168

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

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

खैर कि सिर्फ सरासर मिलावटरहित beaty की बात है। अच्छा काम, केविन कॉस्टनर। – Fuser97381

58

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

यह केवल रूबी 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

असल में, मेरा मानना ​​है कि define_method पर ब्लॉक तर्क समर्थन स्प्लट करते हैं, जो डिफ़ॉल्ट तर्कों को परिभाषित करने के लिए एक राउंड-ए-बाउट तरीका भी प्रदान कर सकता है। – Chinasaur

+1

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

+0

धन्यवाद, मैं इसके बारे में भूल गया। अब तय –

74

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

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 शुरू की डबल सूचक ** (दो सितारों) जो (I quote) करता है:

रूबी 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| 
    # ... 

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

+0

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

+1

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

+0

मैंने इस उत्तर को संयुक्त http://stackoverflow.com/questions/4470108/when-monkey-patching-a-method-can-you-call-the-overridden-method-from-the-new-i पर ओवरराइट करने के तरीके को स्वीकार करने के लिए स्वीकार्य उत्तर (ओवरराइड नहीं) रनटाइम पर एक विधि जो वैकल्पिक तर्क और एक ब्लॉक लेती है और अभी भी मूल विधि को तर्क और ब्लॉक के साथ कॉल करने में सक्षम हो सकती है। आह, रूबी। विशेष रूप से, मुझे एक मेजबान के लिए एक एकल एपीआई कॉल के लिए मेरे देव env में Savon :: Client.request को ओवरराइट करने की आवश्यकता है, मैं केवल उत्पादन में ही पहुंच सकता हूं। चीयर्स! – pduey

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