2011-02-04 6 views
19
def class A 
    def a 
    raise "hi" #can't be reached 
    end 

    class B 
    def b 
     a() #doesn't find method a. 
    end 
    end 
end 

मैं बी से आह्वान करना चाहता हूं और अपवाद बढ़ा सकता हूं। मैं कैसे कर सकता हूँ?रूबे में बाहरी कक्षा में एक नेस्टेड क्लास एक विधि का उपयोग कैसे कर सकता है?

+0

'बी' को 'ए' का उत्तराधिकारी बनाएं? – adamax

उत्तर

25

रूबी में घोंसला वाले वर्ग नहीं हैं।

विरासत के माध्यम से, व्यवहार प्राप्त करने का एकमात्र तरीका है, ठीक है।

यदि आप अपना कोड काम करना चाहते हैं, तो आपको नेस्टेड कक्षाओं का समर्थन करने वाली भाषा का उपयोग करने की आवश्यकता है।

  • BETA, भाषा जो नेस्टेड कक्षाएं शुरू की (और उसके उत्तराधिकारी gbeta)
  • Newspeak
  • : हालांकि यह एक अविश्वसनीय रूप से स्वच्छ और शक्तिशाली सुविधा है, मैं दुर्भाग्य से केवल दो भाषाओं कि कक्षाओं नेस्ट है के बारे में पता

मुझे किसी अन्य के बारे में पता नहीं है।

जावा में नेस्टेड कक्षाएं नामक एक रचना है, लेकिन उनके पास कुछ दुर्भाग्यपूर्ण डिज़ाइन सीमाएं हैं।

अपने उदाहरण में ऊपर, यह वर्ग B कि A अंदर नेस्टेड है, यह निरंतरB कि A अंदर नेस्टेड है नहीं है। इस बारे में सोचो: A::B और C:

C = A::B 

अब, वर्ग दो नाम के तहत उपलब्ध है। यह तुरंत स्पष्ट होना चाहिए कि C वैश्विक है और A के अंदर घोंसला नहीं है। (ठीक है, वास्तव में, CObject के अंदर घोंसला है, क्योंकि वास्तव में वैश्विक स्थिरांक नहीं हैं, लेकिन यह बिंदु के बगल में है।) लेकिन C और A::B समान वर्ग हैं, यह स्पष्ट रूप से घोंसला और घोंसला नहीं हो सकता है। केवल तार्किक निष्कर्ष यह है कि कक्षा स्वयं घोंसला नहीं है।

नेस्टेड कक्षाओं की परिभाषित विशेषता यह है कि विधि लुकअप दो आयामों के साथ जाता है: विरासत श्रृंखला, और घोंसले के माध्यम से बाहर। रुबी, सभी ओओ भाषाओं में 99.9% की तरह, केवल पूर्व का समर्थन करता है। (कुछ अर्थों में, घोंसले वाले वर्ग न केवल अपने सुपरक्लास की विशेषताएं, बल्कि आसपास के वर्ग की विशेषताओं को भी प्राप्त करते हैं।)

+0

स्पष्टीकरण टिप्पणी जोड़ने के लिए धन्यवाद, मेरे द्वारा +1। –

+2

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

+0

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

0

a कक्षा A कक्षा के लिए कक्षा विधि होना चाहिए?

class A 
    def self.a 
    raise "hi" 
    end 
    class B 
    def b 
     A::a 
    end 
    end 
end 

A::B.new.b 

आप एक उदाहरण विधि के रूप में रखना चाहते हैं, तो आप स्पष्ट रूप से यह करने के लिए कॉल एक उदाहरण पर, उदाहरण के A.new.a के लिए की तरह होगा।

+0

नहीं, मैं वास्तव में आंतरिक कक्षाओं, न्यूज़पीक शैली का मतलब था। – nes1983

10

यह सिर्फ lulz के लिए है:

class A 
    def a 
    puts "hello from a" 
    end 

    class B 
    def b 
     Module.nesting[1].new.a() 
    end 
    end 
end 
+0

यह केवल तभी काम कर सकता है जब पूरी चीज मॉड्यूल के अंदर हो। –

3

आप तो नेस्टेड वर्ग बाहरी वर्ग का विस्तार करने के लिए, तो ऐसा करना चाहते हैं:

class Outer 

    class Inner < Outer 
    def use_outer_method 
     outer_method("hi mom!") 
    end 
    end 

    def outer_method(foo) 
    puts foo 
    end 

end 

foo = Outer::Inner.new 
foo.use_outer_method  #<= "hi mom" 
foo.outer_method("hi dad!") #<= "hi dad" 
4

मैं आम तौर पर कुछ इस तरह करते हैं:

class A 
    def a 
    puts "hi" 
    end 

    def createB 
    B.new self 
    end 

    class B 
    def initialize(parent) 
     @parent=parent 
    end 

    def b 
     @parent.a 
    end 
    end 
end 

A.new.createB.b 
1

अच्छी तरह से आपकी परिस्थितियों के आधार पर वास्तव में एक समाधान है, उस पर एक बहुत आसान है। रूबी ऑब्जेक्ट द्वारा कैप्चर नहीं किए गए विधि कॉल को पकड़ने की अनुमति देता है। तो अपने उदाहरण के लिए आप कर सकता है:

def class A 
    def a 
    raise "hi" #can't be reached 
    end 

    class B 
    def initialize() 
     @parent = A.new 
    end 

    def b 
     a() #does find method a. 
    end 

    def method_missing(*args) 
     if @parent.respond_to?(method) 
     @parent.send(*args) 
     else 
     super 
     end 
    end 
    end 
end 

तो फिर आप ऐसा करते हैं, तो:

A::B.new().b 

आपको मिलेगा:

!! #<RuntimeError: hi> 

यह शायद एक तरह कुछ बनाने के लिए एक आसान तरीका है सबकंट्रोलर जो केवल कुछ गतिविधियों को संभालता है, लेकिन आसानी से मूल नियंत्रक विधियों को कॉल कर सकता है (हालांकि आप मूल नियंत्रक में प्रारंभकर्ता में तर्क के रूप में भेजना चाहते हैं)।

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

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