2016-02-11 8 views
11

मैं अपने आप में Kernel बढ़ाया और उदाहरण विधि Kernel#abort की परिभाषा के भीतर, मैं सिंगलटन विधि Kernel.abort कहा जाता है में एक उदाहरण विधि के भीतर एक सिंगलटन विधि कॉलिंग:एक मॉड्यूल है जो अपने आप फैली

module Kernel 
    extend self 

    def abort 
    puts "Press ENTER to exit..." 
    gets 
    Kernel.abort 
    end 
end 

abort 

जब मैं फोन Kernel#abort, ऐसा लगता है कि Kernel.abort विधि परिभाषा के अंदर कॉल मूल Kernel#abort (Kernel.abort के रूप में विस्तारित) को संदर्भित करता है।

रूबी कैसे पता है जब मैं Kernel.abort लिखते हैं, मेरा मतलब है कि मूल abort विधि, नहीं एक मैं अभी बनाया है? मैं अभी हाल ही में बनाई गई नई abort विधि को कैसे कॉल करूं?

+0

यदि आप रिकर्सन चाहते हैं, तो 'कर्नेल.बॉर्ट' के बजाय' abort' का उपयोग करें। –

+0

'abort' अंतर्निहित 'स्वयं' के साथ एक कॉल है। 'कर्नेल.बॉर्ट' में 'कर्नेल' स्पष्ट 'स्वयं' है, आप उस ऑब्जेक्ट को निर्दिष्ट करते हैं जिस पर विधि को कॉल किया जाना चाहिए। ओह, और मैंने आपका प्रश्न दोबारा खोल दिया। –

+0

मुझे पूरा यकीन नहीं है कि नाम रिज़ॉल्यूशन यहां कैसे काम करता है, इसलिए मैं कोई जवाब पोस्ट नहीं कर रहा हूं। इस सवाल को पहले से ही इस साइट पर पूछा जाना चाहिए था, हालांकि :) –

उत्तर

4

Kernel.abort को पहले उदाहरण विधि Kernel#abort परिभाषित करके परिभाषित किया गया है और फिर इसे module_function के साथ एक सिंगलटन विधि भी बना दिया गया है। (This is definitely the case in Rubinius; मुझे इसे एमआरआई स्रोत में नहीं मिला लेकिन नीचे देखें।) module_functionmakes a copy of the method. जब आप abort को फिर से परिभाषित करते हैं तो आप इंस्टेंस विधि को फिर से परिभाषित करते हैं लेकिन सिंगलटन प्रति नहीं।

ObjectKernel शामिल हैं, इसलिए जब आप कहते हैं abort आप उदाहरण विधि है, जो आप नए सिरे से परिभाषित किया है मिलता है, लेकिन जब आप कहते हैं Kernel.abort आप सिंगलटन विधि है, जो आप नए सिरे से परिभाषित नहीं किया है मिलता है।

यदि आप वास्तव में abort में रिकर्सन का उपयोग करना चाहते हैं, या सिर्फ यह दिखाने के लिए कि यह स्पष्टीकरण सही है, तो विधि को फिर से परिभाषित करने के बाद module_function :abort पर कॉल करें। सिंगलटन विधि को इंस्टेंस विधि के समान ही अपडेट किया जाएगा और दोनों विधियों की पुनरावृत्ति होगी।

ध्यान दें कि abort के इंस्टेंस संस्करण को फिर से परिभाषित करने के लिए आपको extend self की आवश्यकता नहीं है। चूंकि KernelObject में पहले से ही शामिल है, आपको केवल सभी ऑब्जेक्ट्स को पुनर्नवीनीकरण संस्करण देखने के लिए इंस्टेंस विधि को फिर से परिभाषित करने की आवश्यकता है। दूसरी तरफ, यदि Kernel ने extend self का उपयोग पहले स्थान पर #abort का खुलासा करने के लिए किया था, तो हम इसे बिना किसी जटिलताओं के फिर से परिभाषित कर सकते थे।

निम्नलिखित यह दर्शाता है कि प्रत्यावर्तन की कमी, उपयोगकर्ता परिभाषित, शुद्ध रूबी तरीकों के साथ होता है यानी कि module_function जिम्मेदार है और देशी तरीकों नहीं हैं:

$ cat foo.rb 
module Foo 
    def bar 
    puts "old version" 
    end 
    module_function :bar 
end 

module Foo 
    def bar 
    puts "new version" 
    Foo.bar 
    end 
end 

Object.include Foo 
bar 
$ ruby foo.rb 
new version 
old version 
+0

धन्यवाद। मैं मॉड्यूल के उपयोग के सभी 3 लेख पढ़ूंगा, फिर इस प्रश्न पर वापस आएं। –

+0

काम से विचलित हो गया, इस सवाल के बारे में भूल गया, क्षमा करें। –

1

आप कुछ इस तरह करना चाहिए:

module Kernel 
    class << self 
     alias :real_abort :abort 
     def abort 
      puts "press enter" 
      gets 
      puts "invoking real abort" 
      real_abort 
     end 
    end 
end 

कारण आईआरबी मूल बीच में बंद करें लागू है और अपने को परिभाषित नहीं किया abort है क्योंकि आईआरबी repl एक बीच में बंद करें विधि thats इसके बारे में एक सी भाषा संस्करण है।

आप जिज्ञासा

[1] pry(main)> show-source abort 

From: process.c (C Method): 
Owner: Kernel 
Visibility: private 
Number of lines: 22 

VALUE 
rb_f_abort(int argc, const VALUE *argv) 
{ 
    rb_check_arity(argc, 0, 1); 
    if (argc == 0) { 
    if (!NIL_P(GET_THREAD()->errinfo)) { 
     ruby_error_print(); 
    } 
    rb_exit(EXIT_FAILURE); 
    } 
    else { 
    VALUE args[2]; 

    args[1] = args[0] = argv[0]; 
    StringValue(args[0]); 
    rb_io_puts(1, args, rb_stderr); 
    args[0] = INT2NUM(EXIT_FAILURE); 
    rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit)); 
    } 

    UNREACHABLE; 
} 

पर show-source कर कोड में से इसे देख सकते हैं आप का उल्लेख बीच में बंद करें thats निष्पादित किया जा रहा कर्नेल नहीं है।गर्भपात, लेकिन वह सी भाषा thats आईआरबी को मैप किया गर्भपात जब आप कमांडलाइन

से यह आह्वान यदि आप चाहते हैं तो यह आपको कुछ इस तरह कर सकता है ताकि आईआरबी repl में abort अपने नए सिरे से परिभाषित abort

def abort; Kernel.abort; end 
पर अमल होगा नीचे दब जाती के लिए

फिर यदि आप abort चलाते हैं तो यह आपके पुनर्नवीनीकरण कर्नेल की निरस्त सिंगलटन विधि का आह्वान करेगा।

+0

मैंने अपने उत्तर में एक उदाहरण जोड़ा जो दिखाता है कि घटना मूल विधि के कारण नहीं है। –

+0

नीचे मतदाता क्या आप मेरे जवाब का खंडन कर सकते हैं और कह सकते हैं कि यह गलत है ?? – uday

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