Accessing module methods with ::

后端 未结 2 913
無奈伤痛
無奈伤痛 2021-01-12 09:14

Documentation I\'ve read tells me to use Module.method to access methods in a module. However, I can use Module::method as well. Is this syntactic sugar, or am I confused?

相关标签:
2条回答
  • 2021-01-12 09:55

    Constant resolution always requires that you use ::.

    Method invocation is idiomatically and usually a period (.), but :: is also legal. This is not just true for so-called module methods, but for invoking any method on any object:

    class Foo
      def bar
        puts "hi"
      end
    end
    
    Foo.new::bar
    #=> hi
    

    It's not so much "syntax sugar" as it is simply alternative syntax, such as the ability to write if or case statements with either a newline, then and newline, or just then.

    It is specifically allowed because Ruby allows methods with the same name as a constant, and sometimes it makes sense to think that they are the same item:

    class Foo
      class Bar
        attr_accessor :x
        def initialize( x )
          self.x = x
        end
      end
      def self.Bar( size )
        Foo::Bar.new( size ) 
      end
    end
    
    p Foo::Bar     #=> Foo::Bar                    (the class)
    p Foo::Bar(42) #=> #<Foo::Bar:0x2d54fc0 @x=42> (instance result from method call)
    

    You see this commonly in Ruby in the Nokogiri library, which has (for example) the Nokogiri::XML module as well as the Nokogiri.XML method. When creating an XML document, many people choose to write

    @doc = Nokogiri::XML( my_xml )
    

    You see this also in the Sequel library, where you can write either:

    class User < Sequel::Model                      # Simple class inheritance
    class User < Sequel::Model(DB[:regular_users])  # Set which table to use
    

    Again, we have a method (Sequel.Model) named the same as a constant (Sequel::Model). The second line could also be written as

    class User < Sequel.Model(DB[:regular_users])
    

    …but it doesn't look quite as nice.

    0 讨论(0)
  • 2021-01-12 10:13

    The :: is called scope resolution operator, which is used to find out under what scope the method, class or constant is defined.

    In the following example, we use :: to access class Base which is defined under module ActiveRecord

    ActiveRecord::Base.connection_config
    # => {:pool=>5, :timeout=>5000, :database=>"db/development.sqlite3", :adapter=>"sqlite3"}
    

    We use :: to access constants defined in module

    > Cat::FURRY_LEVEL
    => 4
    > Cat.FURRY_LEVEL
    => undefined method `FURRY_LEVEL' for Cat:Module (NoMethodError)
    

    The . operator is used to call a module method(defined with self.) of a module.

    Summary: Even though both :: and . does the same job here, it is used for different purpose. You can read more from here.

    0 讨论(0)
提交回复
热议问题