2010-01-26 7 views
6

रूबी में, हम निम्नलिखित कोड शो की तरह संबंधित सुपर क्लास की सिंगलटन विधि को कॉल करने के लिए सिंगलटन विधि के भीतर super का उपयोग कर सकते हैं।रुबी में बेस और व्युत्पन्न वर्ग के मेटाक्लास के बीच संबंध क्या है?

class Base 
    def self.class_method 
    puts "Base class method" 
    end 
end 

class Derived < Base 
    def self.class_method 
    puts "Derived class method" 
    super 
    end 
end 

Derived.class_method 
# Derived class method 
# Base class method 

हालांकि, मैं नहीं लगते काफी हो कैसे Derived.class_method भीतर super करने के लिए कि कॉल Base.class_method तक पहुंच सकता है। मुझे लगता है कि class_method को उनके मेटाक्लास पर परिभाषित किया गया है, क्या इसका मतलब है कि उनके मेटाक्लास के माता-पिता/बाल संबंध हैं? मैं इस सवाल पूछ रहा हूँ क्योंकि मैं कहीं वहाँ आधार bettwen संबंध किसी तरह का और व्युत्पन्न वर्ग 'metaclass है देखकर याद (लेकिन मैं नहीं कर सकता:

अद्यतन (मैं काफी है कि प्रयोगों द्वारा पुष्टि नहीं कर सकते) इसे और ढूंढें)। यह जानने के अलावा कि वास्तव में super काम करता है, मैं यह भी पुष्टि करना चाहता हूं कि दो मेटाक्लास पूरी तरह से अलग हैं या नहीं।

उत्तर

11

यहाँ खेलने में चार वर्ग वस्तुओं के होते हैं:

<Class>---class---><Class> 
Base    #Base 
^    ^
    |     | 
    |     | 
super    super 
    |     | 
    |     | 
<Class>   <Class> 
Derived---class--->#Derived 

नामकरण:

  • < ...> प्रत्येक वस्तु के वर्ग है।
  • कक्षा का नाम दूसरी पंक्ति पर है।
  • यदि नाम # से शुरू होता है, तो यह eigenclass (उर्फ सिंगलटन क्लास) है।
  • एक वर्ग के सुपर क्लास वर्ग के वर्ग के लिए
  • वर्ग अंक के सुपर अंक।

जब आप Derived.class_method फोन, रूबी "सही और फिर" नियम इस प्रकार हैं: सबसे पहले वस्तु की क्लास में जाएं, फिर सुपर क्लास चेन, अनुवर्ती जब विधि पाया जाता है रोक:

  • "class_method" कॉल का प्राप्तकर्ता व्युत्पन्न है। तो Derived के क्लास ऑब्जेक्ट के दाईं ओर श्रृंखला का पालन करें, जो इसकी eigenclass (#Derived) है।
  • व्युत्पन्न विधि को परिभाषित नहीं करता है, तो रूबी श्रृंखला # व्युत्पन्न के सुपर क्लास के लिए श्रृंखला है, जो #Base है इस प्रकार है।

  • विधि वहाँ पाया जाता है, तो रूबी # Base.class_method को संदेश डिस्पैच

आप नहीं लगता कि मैं अपने सिर के ऊपर से यह सब सामान जानता था, तुमने किया था? यहां वह जगह है जहां मेरे मस्तिष्क को यह मेटा जुजू मिला: Metaprogramming Ruby

भाग 2 एक "eigenclass" (उर्फ "सिंगलटन वर्ग") बनाने के लिए

class Object 
    def eigenclass 
    class << self 
     self 
    end 
    end 
end 

इस विधि छुपा किसी भी वस्तु का eigenclass वापस आ जाएगी से बाहर आते हैं। अब, कक्षाओं के बारे में क्या? वे वस्तुएं भी हैं।

p Derived.eigenclass    # => #<Class:Derived> 
p Derived.eigenclass.superclass # => #<Class:Base> 
p Base.eigenclass     # => #<Class:Base> 

नोट: ऊपर रूबी 1.9 से है। जब रूबी 1 के तहत चलाए।

p Derived.eigenclass.superclass # => #<Class:Class> 
+0

वहाँ एक रास्ता #Base और #Derived के बीच के रिश्ते को 'देख' है? उदाहरण के लिए, सामान्य '। सुपरक्लास' की तरह। – bryantsai

+0

मैंने उस चाल को जोड़ा जो छिपाने से बाहर एक ईजिनक्लास प्राप्त करता है। लेकिन आरेख इस बात से सुसंगत नहीं है कि चाल क्या दिखाती है :( –

+0

अच्छी तरह से ... # <कक्षा: व्युत्पन्न> #नहीं है, यह मेरी समस्या है ... #Derived से #Base का लिंक वास्तव में मौजूद है? – bryantsai

3

यह चित्र संबंध बताते हैं:: 8, आप एक आश्चर्य मिल http://banisterfiend.wordpress.com/2008/11/25/a-complete-ruby-class-diagram/

इसके अलावा, यहां कुछ अन्य पोस्ट अधिक eigenclasses की पेचीदगियों को समझाने हैं: http://www.klankboomklang.com/2007/10/05/the-metaclass/

http://www.klankboomklang.com/2007/09/21/the-singleton-class/

और यहां एक काफी कठिन चल रहा है जो आपको बताएगा उससे अधिक बताता है: http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/

+1

अंत में मैं आपकी हार्ड-पोस्ट पोस्ट पढ़ने के लिए चारों ओर मिल गया। उत्तम सामग्री! –

4

को स्पष्ट और सही कर क्या मैं जिस तरह से रूबी छुपाता/eigenclasses को उजागर करता है के बारे में टिप्पणी में लिखा है के लिए, यहाँ स्थिति है:

रूबी 1.8:

(1) Object#class विधि हमेशा पहली वास्तविक रिटर्न (गैर eigenclass या iclass) वास्तविक किसी ऑब्जेक्ट की कक्षा का सुपरक्लास। , उदा,

o = Object.new 
class << o; end 
o.class #=> returns Object, even though the _actual_ class is the eigenclass of o 

दूसरे शब्दों में, Object#class विधि एक eigenclass वापस कभी नहीं होगा, यह उन्हें के ऊपर से गुजरता है और इसके बजाय पहले 'असली' वर्ग यह वंशानुगत पदानुक्रम में पाता है देता है।

(2) Class#superclass विधि में दो मामले हैं। अगर रिसीवर एक ईजिनक्लास नहीं है तो यह बस सुपरक्लास लौटाता है। हालांकि, अगर रिसीवर एक ईजिनक्लास है तो यह विधि रिसीवर के वास्तविक (यानी वास्तविक रूप से वास्तविक नहीं) कक्षा लौटाती है।

# case where receiver is a normal class (i.e not an eigenclass) 
Module.superclass #=> Object (behaves as expected) 

# case where receiver is an eigenclass 
class << Module; superclass; end #=> returns Class, this is NOT the superclass 

ऊपर से, Class#superclass बर्ताव करता है एक सामान्य वर्ग के मामले में अपेक्षा के अनुरूप है, लेकिन eigenclass उदाहरण के लिए यह मॉड्यूल की eigenclass की सुपर क्लास में कहा गया है जो सच नहीं है क्लास है। इस आरेख से http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/ हम जानते हैं कि मॉड्यूल के ईजेनक्लास का सुपरक्लास वास्तव में ऑब्जेक्ट का ईजिनक्लास है। मुझे यकीन नहीं है कि रूबी 1.8 में यह अजीब व्यवहार क्यों है।

रूबी 1.9:

(1) Object#class विधि हूबहू 1.8 संस्करण के लिए व्यवहार करता है।

(2) Class#superclass विधि में अब दो मामले नहीं हैं, अब यह सामान्य वर्गों के समान तरीके से ईगेंक्लेस का इलाज करता है और वास्तविक सुपरक्लास को अपेक्षित रूप से देता है।

, उदा,

class << Module; superclass; end #=> #<Class:Object> 
संबंधित मुद्दे

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