रूबी के दोहरे-उपनिवेश क्या हैं :: :: `?


427

यह दोहरे-उपनिवेश क्या है ::? जैसे Foo::Bar

मुझे एक मिला परिभाषा :

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

क्या अच्छा है स्कोप (निजी, संरक्षित) अगर आप बस ::कुछ भी उजागर करने के लिए उपयोग कर सकते हैं ?


175
भविष्य के googlers के लाभ के लिए, यदि आप एक प्रतीक की खोज करने की कोशिश कर रहे हैं, तो symbolhound.com पर
एंड्रयू ग्रिम

1
संभव डुप्लिकेट? stackoverflow.com/questions/2276905/what-does-mean-in-ruby
iX3


6
आपको आशीर्वाद, @AndrewGrimm इस सप्ताह मैंने जो सबसे अच्छी चीज देखी है।
18

जवाबों:


381

::मूल रूप से एक नेमस्पेस रिज़ॉल्यूशन ऑपरेटर है। यह आपको कक्षाओं में मॉड्यूल, या कक्षा-स्तरीय आइटम तक पहुंचने की अनुमति देता है। उदाहरण के लिए, मान लें कि आपके पास यह सेटअप है:

module SomeModule
    module InnerModule
        class MyClass
            CONSTANT = 4
        end
    end
end

आप CONSTANTमॉड्यूल के बाहर से पहुंच सकते हैं SomeModule::InnerModule::MyClass::CONSTANT

यह एक वर्ग पर परिभाषित उदाहरण विधियों को प्रभावित नहीं करता है, क्योंकि आप एक अलग वाक्यविन्यास (डॉट .) के साथ उन तक पहुंचते हैं ।

प्रासंगिक नोट: यदि आप शीर्ष स्तर के नाम स्थान पर वापस जाना चाहते हैं, तो यह करें: :: SomeModule - Benjamin Oakes


5
उदाहरण के लिए C # में, हाँ। दूसरी ओर सी ++ (और रूबी) ::नेमस्पेस रिज़ॉल्यूशन के लिए उपयोग किया जैसे किstd::cout << "Hello World!";
जेरी फ़र्नहोलज़

142
प्रासंगिक नोट: यदि आप शीर्ष-स्तरीय नाम स्थान पर वापस जाना चाहते हैं, तो यह करें: ::SomeModule
बेंजामिन

5
@ बैंजामिन प्रमुख कॉलन निहित हैं, जब तक कि मैं किसी अन्य मॉड्यूल के अंदर एक कुछ मॉड्यूल नहीं होता और मैं शीर्ष-स्तर एक प्राप्त करना चाहता हूं, सही?
जोइस

7
@ जो हां। यह मददगार हो सकता है यदि आप सुनिश्चित करना चाहते हैं कि आप शीर्ष स्तर के नामस्थान पर एक स्थिरांक का उल्लेख कर रहे हैं या किसी अन्य मॉड्यूल में समान नाम के साथ एक स्थिरांक (जैसे :: SomeOtherModule :: ClassMethods)।
बेंजामिन ने

2
यह बहुत हद तक C ++ के स्कोप ऑपरेंड की तरह है
lkahtz

111

यह सरल उदाहरण इसे दिखाता है:

MR_COUNT = 0        # constant defined on main Object class
module Foo
  MR_COUNT = 0
  ::MR_COUNT = 1    # set global count to 1
  MR_COUNT = 2      # set local count to 2
end

puts MR_COUNT       # this is the global constant: 1
puts Foo::MR_COUNT  # this is the local constant: 2

Http://www.tutorialspoint.com/ruby/ruby_operators.htm से लिया गया


हालांकि यह चेतावनी का कारण बनता है। क्या चेतावनी से बचने का कोई तरीका है?
NullVoxPopuli

3
@NullVoxPopuli आम तौर पर स्थिरांक को संशोधित करना वास्तव में एक बुरी बात है, लेकिन अगर आप उदाहरण के लिए एक बुरी तरह से लिखे गए मणि में एक निरंतरता को संशोधित करना चाहते हैं और इसे कांटा नहीं करना चाहते हैं, तो इसका उपयोग मॉड्यूल को परिभाषित करने वाले .send (: remove_const) का उपयोग करके किया जा सकता है। यह, फिर स्थिरांक को फिर से परिभाषित करना।
BookOfGreg

71

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

जब आप ActiveRecord::Baseरेल में देखते हैं तो इसका मतलब है कि रेल में कुछ ऐसा है

module ActiveRecord
  class Base
  end
end

अर्थात एक Baseमॉड्यूल के अंदर बुलाया जाने वाला एक वर्ग जिसे ActiveRecordतब संदर्भित किया जाता है ActiveRecord::Base(आप इसे एक्टिवरकॉर्ड- nn / lib / active_record / base.rb में रेल स्रोत में पा सकते हैं)

मॉड्यूल में परिभाषित स्थिरांक का उपयोग करने के लिए :: का एक सामान्य उपयोग है

module Math
  PI = 3.141 # ...
end

puts Math::PI

::ऑपरेटर तरीकों में से बाईपास दृश्यता के लिए आप की अनुमति नहीं है, निजी या संरक्षित चिह्नित।


7
इसलिए यदि किसी के पास है class MyClass < ActiveRecord::Base, तो इसका मतलब यह है कि MyClass केवल वर्ग आधार से विधियां प्राप्त करता है और ActiveRecord मॉड्यूल के अंदर कुछ भी नहीं?
चार्ली पार्कर

2
"नाम" के बजाय इस नाम स्थान रिज़ॉल्यूशन के लिए विशेष डबल-कॉलन का उपयोग क्यों करें। इसके लिए भी? संदर्भ और पूंजीकरण अर्थ के भ्रम को रोक देगा भले ही हम "" का उपयोग कर रहे हों, क्या यह नहीं होगा?
योना

3
@ जोना के कुछ मामले हैं जहां यह अस्पष्ट होगा। उदाहरण पर विचार class Foo; Baz = 42; def self.Baz; "Baz method!"; end; end(पूरी तरह से मान्य) Foo::Baz # => 42और Foo.Baz # => "Baz method!"। ध्यान दें कि Foo::Baz()(कोष्ठक के साथ) भी विधि को कॉल करेगा।
मिकज

3
इसलिए उपयोग के मामले में यह वर्ग को स्थिर रखने की क्षमता और एक वर्ग विधि है जो सटीक समान नाम है? यह सुविधा के पक्ष में एक मजबूत तर्क की तरह नहीं लगता है। व्यक्तिगत रूप से मैं बहुत अधिक उस क्षमता को खो देता हूं (वैसे भी परेशानी की तरह लगता है), डबल-कॉलन खो देते हैं, और उपयोग करते हैं "।" नाम रखने के लिए भी .... शायद वहाँ अतिरिक्त उपयोग के मामले हैं यह हल करती है?
योना

26

क्या अच्छा है गुंजाइश (निजी, संरक्षित) यदि आप बस उपयोग कर सकते हैं :: कुछ भी उजागर करने के लिए?

रूबी में, सब कुछ उजागर है और सब कुछ कहीं और से संशोधित किया जा सकता है।

यदि आप इस तथ्य से चिंतित हैं कि कक्षाएं "वर्ग परिभाषा" के बाहर से बदली जा सकती हैं, तो रूबी शायद आपके लिए नहीं है।

दूसरी ओर, यदि आप जावा की कक्षाओं के बंद होने से निराश हैं, तो रूबी शायद वही है जिसे आप खोज रहे हैं।


1
मैंने सुना है कि कुछ माणिकवादियों का कहना है कि उदाहरण चर उजागर नहीं होते हैं, यहां तक ​​कि attr_accessorकेवल उन तरीकों को बनाता है जो चर को संशोधित करते हैं। (इसके बाद फिर से instance_eval)
एंड्रयू ग्रिम

4
सही है, वहाँ instance_eval। लेकिन वहाँ भी है instance_variable_getऔर instance_variable_set। रूबी सिर्फ बाधाओं के लिए बहुत गतिशील है।
yfeldblum

12

पिछले उत्तरों में जोड़कर, ::उदाहरण के तरीकों का उपयोग करने के लिए रूबी मान्य है । सभी निम्नलिखित मान्य हैं:

MyClass::new::instance_method
MyClass::new.instance_method
MyClass.new::instance_method
MyClass.new.instance_method

सर्वोत्तम प्रथाओं के अनुसार, मेरा मानना ​​है कि केवल अंतिम की सिफारिश की जाती है।


11

नहीं, यह हर विधि का उपयोग करने के लिए नहीं है, यह एक "रिज़ॉल्यूशन" ऑपरेटर है, अर्थात, आप इसका उपयोग निरंतर / स्थिर प्रतीक के दायरे (या स्थान जिसे आप कह सकते हैं) को हल करने के लिए कर सकते हैं।

उदाहरण के लिए, अपनी पहली पंक्ति में, रेल इसका उपयोग ActiveRecord.Module के अंदर बेस क्लास को खोजने के लिए करते हैं। आपके दूसरे में इसका उपयोग रूट क्लास की क्लास विधि (स्टैटिक), आदि का पता लगाने के लिए किया जाता है।

इसका उपयोग किसी भी चीज को उजागर करने के लिए नहीं किया जाता है, इसका उपयोग आपके स्कोप के आसपास सामान का "पता लगाने" के लिए किया जाता है।

http://en.wikipedia.org/wiki/Scope_resolution_operator


द्वारा (स्थिर) "क्या आपका मतलब है" (ड्रा) "?"
मुल्तेमी

8

हैरानी की बात है कि यहां सभी 10 जवाब एक ही बात कहते हैं। '::' एक नाम स्थान रिज़ॉल्यूशन ऑपरेटर है, और हाँ यह सच है। लेकिन एक गोटा है जिसे आपको नाम स्वरूप रिज़ॉल्यूशन ऑपरेटर के बारे में महसूस करना होगा जब यह निरंतर लुकअप एल्गोरिथ्म में आता है । जैसा कि मैत्ज़ ने अपनी पुस्तक 'द रूबी प्रोग्रामिंग लैंग्वेज' में लिखा है, निरंतर खोज के कई चरण हैं। सबसे पहले, यह शाब्दिक दायरे में एक स्थिरांक को खोजता है जहां निरंतर संदर्भित होता है। यदि यह शाब्दिक दायरे के भीतर स्थिरांक नहीं पाता है, तो यह वंशानुक्रम पदानुक्रम की खोज करता है । इस निरंतर खोज एल्गोरिथ्म के कारण, नीचे हमें अपेक्षित परिणाम मिलते हैं:

module A
  module B
      PI = 3.14
      module C
        class E
          PI = 3.15
        end
        class F < E
          def get_pi
            puts PI
          end
        end
      end
  end
end
f = A::B::C::F.new
f.get_pi
> 3.14

जबकि F, E से विरासत में मिला है, B मॉड्यूल F के लेक्सिकल दायरे में है। नतीजतन, F इंस्टेंसेस मॉड्यूल B में परिभाषित निरंतर PI को संदर्भित करेगा। अब यदि मॉड्यूल B ने PI को परिभाषित नहीं किया है, तो F इंस्टेंसेस PI को संदर्भित करेगा। सुपरक्लास ई में निरंतर परिभाषित।

लेकिन क्या होगा अगर हम नेस्टिंग मॉड्यूल के बजाय '::' का उपयोग करें? क्या हमें वही परिणाम मिलेगा? नहीं!

नेस्टेड मॉड्यूल को परिभाषित करते समय नेमस्पेस रिज़ॉल्यूशन ऑपरेटर का उपयोग करके, नेस्टेड मॉड्यूल और कक्षाएं अब उनके बाहरी मॉड्यूल के लेक्सिकल दायरे में नहीं हैं। जैसा कि आप नीचे देख सकते हैं, ए :: बी में परिभाषित पीआई ए :: बी :: सी :: डी के शाब्दिक दायरे में नहीं है और इस तरह हम असंगठित स्थिर हो जाते हैं जब गेट_पीआई आवृत्ति विधि में पीआई को संदर्भित करने का प्रयास करते हैं:

module A
end

module A::B
  PI = 3.14
end

module A::B::C
  class D
    def get_pi
      puts PI
    end
  end
end
d = A::B::C::D.new
d.get_pi
NameError: uninitialized constant A::B::C::D::PI
Did you mean?  A::B::PI

4

यह आपकी परियोजना से जुड़े अन्य कोड के साथ परिभाषाओं को बंद करने से रोकने के बारे में है। इसका मतलब है कि आप चीजों को अलग रख सकते हैं।

उदाहरण के लिए आपके पास अपने कोड में "रन" नामक एक विधि हो सकती है और आप अभी भी "रन" पद्धति के बजाय अपनी विधि को कॉल कर पाएंगे जो कि आपके द्वारा लिंक किए गए कुछ अन्य लाइब्रेरी में परिभाषित की गई है।


3
module Amimal
      module Herbivorous
            EATER="plants" 
      end
end

Amimal::Herbivorous::EATER => "plants"

:: एक स्कोप बनाने के लिए उपयोग किया जाता है। लगातार मॉड्यूल को 2 मॉड्यूल से एक्सेस करने के लिए हमें मॉड्यूल को निरंतर तक पहुंचने की गुंजाइश की आवश्यकता होती है


3

पटरियों पर रूबी ::नेमस्पेस रिज़ॉल्यूशन के लिए उपयोग करता है ।

class User < ActiveRecord::Base

  VIDEOS_COUNT = 10
  Languages = { "English" => "en", "Spanish" => "es", "Mandarin Chinese" => "cn"}

end

इसके प्रयेाग के लिए :

User::VIDEOS_COUNT
User::Languages
User::Languages.values_at("Spanish") => "en"

इसके अलावा, अन्य उपयोग है: नेस्टेड मार्गों का उपयोग करते समय

OmniauthCallbacksController उपयोगकर्ताओं के तहत परिभाषित किया गया है।

और इस रूप में रूट किया गया:

devise_for :users, controllers: {omniauth_callbacks: "users/omniauth_callbacks"}


class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

end
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.