2009-08-09 16 views
34

स्थिति: मेरे पास कई कक्षाएं हैं जिनमें प्रत्येक को कॉन्फ़िगरेशन हैश के साथ एक चर रखना चाहिए; प्रत्येक वर्ग के लिए एक अलग हैश लेकिन एक वर्ग के सभी उदाहरणों के लिए समान है।रूबी: कक्षा चर के साथ काम करने वाला इनहेरिट कोड

सबसे पहले, मैं इस

class A 
    def self.init config 
    @@config = config 
    end 

    def config 
    @@config 
    end 
end 

class B < A; end 
class C < A; end 

तरह की कोशिश की लेकिन जल्द ही देखा है कि यह उस तरह से क्योंकि @@ config ए, बी या सी, इस प्रकार नहीं के संदर्भ में आयोजित किया जाता है काम नहीं होगा:

B.init "bar" 
p B.new.config # => "bar" 
p C.new.config # => "bar" - which would be nil if B had it's own @@config 

C.init "foo" 
p B.new.config # => "foo" - which would still be "bar" if C had it's own @@config 
p C.new.config # => "foo" 

मैं इस तरह इसे प्रयोग के बारे में सोचा:

modules = [B, C] 
modules.each do |m| 
    m.init(@config[m.name]) 
end 
# ... 
B.new # which should then have the correct config 

अब, यह मेरे लिए स्पष्ट है क्यों ऐसा होता है, लेकिन मैं वें के बारे में यकीन नहीं है इस तरह होने के कारण।

क्या यह अन्य तरीकों से भी काम नहीं कर सका, वर्ग वर्ग को उपclass के संदर्भ में पकड़े हुए?

मुझे जो भी परेशान पाया गया वह तथ्य यह था कि सुपरक्लास में 'इन' कहलाते समय स्वयं हमेशा उप-वर्ग होता है। इससे, मुझे पहले उम्मीद थी कि सुपरक्लास से कोड उपclass के संदर्भ में निष्पादित किया गया है।

इसके बारे में कुछ ज्ञान की सराहना की जाएगी।

दूसरी तरफ, मुझे यह स्वीकार करना होगा कि यह इस तरह से काम करता है और मुझे ऐसा करने का दूसरा तरीका ढूंढना है।

क्या ऐसा करने के लिए कोई "मेटा" तरीका है? (मैं class_variable_set आदि के साथ है, लेकिन कोई भाग्य के साथ की कोशिश की)

या हो सकता है कि 'init' पहली जगह में त्रुटिपूर्ण विधि के पूरे विचार है और वहाँ कुछ अन्य "पैटर्न" यह करने के लिए है?

मैं सिर्फ @@ config एक हैश बना सकता हूं, सभी कॉन्फ़िगरेशन रखता हूं और हमेशा सही चुनता हूं, लेकिन मुझे लगता है कि थोड़ा अजीब .. (इस तरह की समस्या को हल करने के लिए विरासत नहीं है?)

उत्तर

94

@@variables कक्षा चर नहीं हैं। वे वर्ग पदानुक्रम चर, यानी वे पूरी क्लास पदानुक्रम के बीच साझा कर रहे हैं, सभी उपवर्गों और सभी उपवर्गों के सभी उदाहरणों भी शामिल है। (यह सुझाव दिया गया है कि @@variables$$variables की तरह $globals के साथ के साथ वास्तव में अधिक सामान्य होना चाहिए। इस तरह से कम भ्रम है। अन्य लोग आगे बढ़ गए हैं और सुझाव देते हैं कि उन्हें भाषा से हटा दिया जाना चाहिए।)

रूबी अर्थ है कि, कहते हैं, जावा (जहां वे स्थिर क्षेत्रों कहा जाता है) उन्हें है में वर्ग चर नहीं है। यह वर्ग चर नहीं है जरूरत है, क्योंकि कक्षाएं भी वस्तुओं रहे हैं, और इसलिए वे किसी भी अन्य वस्तु की तरह उदाहरण चर हो सकता है। आपको केवल @ एस को निकालना है। (और तुम वर्ग उदाहरण चर के लिए एक्सेसर विधि प्रदान करना होगा।)

class A 
    def self.init config 
    @config = config 
    end 

    def self.config # This is needed for access from outside 
    @config 
    end 

    def config 
    self.class.config # this calls the above accessor on self's class 
    end 
end 

, चलो इस एक सा को आसान बनाने में करते हैं के बाद से A.config स्पष्ट रूप से सिर्फ एक attribute_reader है:

class A 
    class << self 
    def init config 
     @config = config 
    end 

    attr_reader :config 
    end 

    def config 
    self.class.config 
    end 
end 

और, वास्तव में, A.init सिर्फ एक अजीब नाम के साथ एक लेखक है, तो चलो यह A.config= को नाम बदलने जाने और इसे एक लेखक बनाते हैं, जिसका अर्थ यह है कि हमारी विधियों की जोड़ी अब सिर्फ एक एक्सेसर जोड़ी है। (जब से हम एपीआई बदल गया है, परीक्षण कोड स्पष्ट रूप से और साथ ही बदलने के लिए है।)

class A 
    class << self 
    attr_accessor :config 
    end 

    def config 
    self.class.config 
    end 
end 

class B < A; end 
class C < A; end 

B.config = "bar" 
p B.new.config # => "bar" 
p C.new.config # => nil 

C.config = "foo" 
p B.new.config # => "bar" 
p C.new.config # => "foo" 

हालांकि, मैं महसूस कर रही कुछ और मौलिक रूप से iffy डिजाइन के बारे में है कि वहाँ हिला नहीं कर सकते, अगर आप इस की जरूरत है बिलकुल।

+0

मुझे नहीं पता कि डिज़ाइन iffy कैसे है। यह सामान्य रूप से करने के लिए एक उचित पर्याप्त चीज की तरह लगता है। – Chuck

+0

यह वही है जो मुझे जानने की ज़रूरत है, बहुत बहुत धन्यवाद! :) वास्तव में नहीं जानते कि और क्या कहना है, अब यह सब इतना स्पष्ट है। इनिट विधि का उद्देश्य एकाधिक चर सेट करने के लिए किया गया था, मुझे सादगी के लिए कॉन्फ़िगरेशन उदाहरण मिला। लेकिन अब आप इसका जिक्र करते हैं, यह शायद एक्सेसर्स के साथ अभी भी क्लीनर है;) फिर से, बहुत बहुत धन्यवाद! –

+0

@Chuck: उदाहरण के लिए, एक इंस्टेंस विधि ('ए # कॉन्फ़िगरेशन ') है जो न तो एक इंस्टेंस विधि कहती है और न ही इंस्टेंस स्टेटस तक पहुंचती है और न ही ओवरराइड हो जाती है। यह छिद्रित उदाहरण का एक आर्टिफैक्ट हो सकता है, यह एक वैध डिजाइन हो सकता है, लेकिन, शायद, यह नहीं है। इसके अलावा, बी और सी ए से विरासत में हैं, लेकिन कुछ भी ओवरराइड नहीं करते हैं, फिर भी, वे किसी भी तरह से एक दूसरे से और ए से अलग व्यवहार करने की उम्मीद कर रहे हैं, भले ही वे सभी समान हैं। दोबारा: शायद समझदार, शायद नहीं। यह सब संदर्भ पर निर्भर करता है, जो निश्चित रूप से किसी भी समझदार निष्कर्ष तक पहुंचने के लिए इस उदाहरण में बहुत छोटा है। –

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