2012-12-07 9 views
7

का उपयोग करने के लिए नीचे दिए गए कोड में, विधि roar कक्षा Lion में परिभाषित नहीं है, लेकिन अभी भी method_missing का उपयोग करके कॉल किया जा सकता है।`method_missing`

class Lion 
    def method_missing(name, *args) 
    puts "Lion will #{name}: #{args[0]}" 
    end 
end 

lion = Lion.new 
lion.roar("ROAR!!!") # => Lion will roar: ROAR!!! 

किस स्थितियों में और मुझे इस method_missing का उपयोग कैसे करना चाहिए? और क्या इसका उपयोग सुरक्षित है?

+0

भूत विधि, आमतौर पर एक मेटाप्रोग्रामिंग टूल, मुझे लगता है। दक्षता के बारे में सावधान रहें। भूत विधि धीमी है। – halfelf

+0

मुझे लगता है कि आप 'क्लास शेर' की बजाय 'कक्षा शेर' का मतलब है। –

+0

@EricWalker: धन्यवाद, टाइपिंग गलती। – tokhi

उत्तर

8

सारांश: उपयोग कब करें? जब यह आपके जीवन को आसान बना देगा और दूसरों के जीवन को जटिल नहीं करता है।


यहां एक उदाहरण है जो दिमाग में आता है। यह redis_failover मणि से है।

# Dispatches redis operations to master/slaves. 
def method_missing(method, *args, &block) 
    if redis_operation?(method) 
    dispatch(method, *args, &block) 
    else 
    super 
    end 
end 

यहां हम जांचते हैं कि क्या विधि कहा जाता है वास्तव में रेडिस कनेक्शन का एक आदेश है। यदि ऐसा है, तो हम इसे अंतर्निहित कनेक्शन में भेजते हैं। यदि नहीं, सुपर पर रिले।

method_missing एप्लिकेशन का एक और प्रसिद्ध उदाहरण ActiveRecord खोजकर्ता है।

User.find_by_email_and_age('[email protected]', 20) 

वहाँ नहीं है, निश्चित रूप से एक विधि find_by_email_and_age। इसके बजाय, method_missing नाम तोड़ता है, भागों का विश्लेषण करता है और find उचित पैरामीटर के साथ आमंत्रित करता है।

9

यह पूरी तरह से सुरक्षित उपयोग करने के लिए उपयोग किया जाता है, बशर्ते आप इसे अपेक्षित तरीकों से उपयोग करें और दूर नहीं ले जाएं। आप जो भी कर सकते हैं वह सब कुछ करने के लायक नहीं है।

method_missing का लाभ यह है कि आप अद्वितीय तरीके से सभी प्रकार की चीजों का जवाब दे सकते हैं।

नुकसान यह है कि आप अपनी क्षमताओं का विज्ञापन नहीं करते हैं। अन्य ऑब्जेक्ट्स जो आपको respond_to? की अपेक्षा करते हैं, उन्हें कुछ पुष्टि नहीं मिलेगी और आपके कस्टम ऑब्जेक्ट का उन तरीकों से इलाज कर सकते हैं जिनके बारे में आप इरादा नहीं रखते हैं।

डोमेन विशिष्ट भाषाओं के निर्माण और घटकों के बीच बहुत ढीला गोंद प्रदान करने के लिए, इस तरह की चीज अमूल्य है।

यह एक अच्छा उदाहरण है जहां यह एक अच्छा फिट है रूबी OpenStruct कक्षा है।

+1

+1 'method_missing' के जुड़वां भाई' answers_to का उल्लेख करने के लिए +1? – akuhn

+7

दरअसल, 'method_missing' का जुड़वां भाई' answer_to_missing 'है? आपको हमेशा * दोनों को एक साथ ओवरराइड करना चाहिए। –

+0

@ JörgWMittag ने कभी भी 'respond_to_missing' के बारे में नहीं सुना है कि एक मणि है !? – akuhn

4

यहाँ मेरा

class Hash 
    def method_missing(sym,*args) 
    fetch(sym){fetch(sym.to_s){super}} 
    end 
end 

की एक पसंदीदा मुझे देता है कौन सा हैश का उपयोग कर सकते मूल्यों के रूप में यदि वे गुण थे है। जेएसओएन डेटा के साथ काम करते समय यह विशेष काम है।

तो उदाहरण के लिए, tweets.collect{|each|each['text']} लिखने के बजाय मैं केवल tweets.collect(&:text) लिख सकता हूं जो बहुत छोटा है। या tweets.first['author'] के बजाय, मैं केवल tweets.first.author लिख सकता हूं जो अधिक प्राकृतिक लगता है। असल में, यह आपको हैश के मूल्यों के लिए जावास्क्रिप्ट-शैली का उपयोग देता है।

 

एनबी, मैं बंदर मेरा दरवाजा किसी भी क्षण में पुलिस पैच की उम्मीद कर रहा हूँ ...

+1

आप एक विधि भी लिख सकते हैं जो 'tweets.collect (& attr (' text ')) की प्रक्रियाओं को उत्सर्जित करता है, जो होगा:' def attr (a); लैम्ब्डा {| ई | ई [ए]}; अंत' – tadman

+0

आप सही हैं, लेकिन फिर मैं 'tweets.first.text' नहीं लिख सकता (मेरी पोस्ट अपडेट की गई)। – akuhn

+0

अपना खुद का रोल करने के बजाय, ओपनस्ट्रक्चर का उपयोग क्यों नहीं करें?एक "नग्न" वस्तु बनाना स्वयं को करना मुश्किल है। यदि आपके पास 'हैश' जैसी चाबियाँ हैं तो यह आंतरिक तरीकों से संघर्ष करेगी। – tadman

3

मैं भी (पाओलो पेरोटा) से एक ब्लॉग पोस्ट जहां यह जब method_missing उपयोग करने के लिए प्रदर्शन किया पाया:

class InformationDesk 
    def emergency 
    # Call emergency... 
    "emergency() called" 
    end 

    def flights 
    # Provide flight information... 
    "flights() called" 
    end 

    # ...even more methods 
end 

चेक करें कि दोपहर के भोजन के दौरान एक सेवा से पूछा गया है या नहीं।

class DoNotDisturb 
    def initialize 
    @desk = InformationDesk.new 
    end 

    def method_missing(name, *args) 
    unless name.to_s == "emergency" 
     hour = Time.now.hour 
     raise "Out for lunch" if hour >= 12 && hour < 14 
    end 

    @desk.send(name, *args) 
    end 
end 

# At 12:30... 
DoNotDisturb.new.emergency # => "emergency() called" 
DoNotDisturb.new.flights # ~> -:37:in `method_missing': Out for lunch (RuntimeError) 
3

सबसे पहले और सबसे महत्वपूर्ण, सर्जीओ टुलेंटसेव के सारांश से चिपके रहें।

इसके अलावा, मुझे लगता है कि उदाहरणों को देखकर method_missing के लिए सही और गलत परिस्थितियों की भावना प्राप्त करने का सबसे अच्छा तरीका है; एक Null Object में method_missing की


मैं हाल ही में किए गए प्रयोग: तो यहाँ एक और सरल उदाहरण है।

  • नल ऑब्जेक्ट ऑर्डर मॉडल के लिए एक प्रतिस्थापन था।

  • ऑर्डर विभिन्न मुद्राओं के लिए अलग-अलग कीमतों को स्टोर करता है।


method_missing के बिना यह इस तरह दिखता है:

class NullOrder 
    def price_euro 
    0.0 
    end 

    def price_usd 
    0.0 
    end 

    # ... 
    # repeat for all other currencies 
end 

method_missing साथ

, मैं करने के लिए इसे छोटा कर सकते हैं: नहीं होने के अतिरिक्त लाभ के साथ

class NullOrder 
    def method_missing(m, *args, &block) 
    m.to_s =~ /price_/ ? 0.0 : super 
    end 
end 

0 को अपडेट करने के लिए (याद रखें)जब मैं Order पर विशेषताओं को जोड़ता हूं।

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