2012-04-06 5 views
15
module Test 
    def self.model_method 
    puts "this is a module method" 
    end 
end 

class A 
    include Test 
end 

A.model_method 

के साथ इस त्रुटि हो जाएगा:मॉड्यूल का 'स्वयं' तरीका वर्ग की सिंगलटन विधि क्यों नहीं बन सकता है?

अपरिभाषित विधि `एक के लिए model_method ': कक्षा (NoMethodError)

लेकिन यह काम करता है जब मैं ए के metaclass का उपयोग करें:

module Test 
    def model_method 
    puts "this is a module method" 
    end 
end 

class A 
    class << self 
    include Test 
    end 
end 

A.model_method 

क्या कोई इसे समझा सकता है?

+1

संभव डुप्लिकेट [? कि एक मॉड्यूल में एक वर्ग विधि को परिभाषित करना संभव है] (http://stackoverflow.com/questions/4699355/is-that-possible-to-define -ए-क्लास-विधि-इन-ए-मॉड्यूल) –

उत्तर

32

तुम दोनों वर्ग के तरीकों और उदाहरण तरीकों जब एक मॉड्यूल सहित एक वर्ग में मिश्रित करना चाहते हैं, तो आप पैटर्न का पालन कर सकते हैं और उदाहरण विधियों को जोड़ने के लिए include। जब कोई मॉड्यूल शामिल होता है, तो यह #included विधि लागू होता है, जिसमें वास्तविक कक्षा शामिल होती है। यहां से आप extend कक्षा को किसी अन्य मॉड्यूल से कुछ क्लास विधियों के साथ कर सकते हैं। यह काफी आम पैटर्न है।

यह भी देखें: http://api.rubyonrails.org/classes/ActiveSupport/Concern.html

की
11

मॉड्यूल समेत इसके उदाहरण विधियों को प्रतिलिपि बनाने के समान है।

आपके उदाहरण में, A पर प्रतिलिपि बनाने के लिए कोई उदाहरण विधि नहीं है। model_method वास्तव में Test की सिंगलटन कक्षा का एक उदाहरण विधि है।


को देखते हुए:

module A 
    def method 
    end 
end 

यह:

module B 
    def method 
    end 
end 

जब आप इसे इस तरह लगता है कि यह सही समझ में आता है:

module B 
    include A 
end 

इस के अनुरूप है:

module B 
    class << self 
    include A 
    end 
end 

B.method 

यहाँ, तरीकों B मॉड्यूल के सिंगलटन वर्ग है, जो उन्हें B की "वर्ग तरीकों" बनाता है पर कॉपी किया जा रहा है।

ध्यान दें कि यह बिल्कुल वही बात है के रूप में:

module B 
    extend A 
end 

हकीकत में, तरीकों कॉपी नहीं किया जा रहा है; कोई डुप्लिकेशन नहीं है। मॉड्यूल बस विधि लुकअप सूची में शामिल है।

module YourModule 
    module ClassMethods 
    def a_class_method 
     puts "I'm a class method" 
    end 
    end 

    def an_instance_method 
    puts "I'm an instance method" 
    end 

    def self.included(base) 
    base.extend ClassMethods 
    end 
end 

class Whatever 
    include YourModule 
end 

Whatever.a_class_method 
# => I'm a class method 

Whatever.new.an_instance_method 
# => I'm an instance method 

मूल रूप से यह अति-सरल करने के लिए, आप extend वर्ग के तरीकों को जोड़ने के लिए:

+1

मेरे जैसे शुरुआती लोगों के लिए, http: //www.railstips पर विस्तार और शामिल करने के बीच के अंतर की चर्चा।संगठन/ब्लॉग/अभिलेखागार/200 9/05/15/शामिल-बनाम-विस्तार-इन-रूबी/इस पोस्ट के साथ संयोजन में पढ़ने में सहायक था। –

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