使用::访问模块方法

我读过的文档告诉我使用Module.method来访问模块中的方法。 但是,我也可以使用Module :: method。 这是语法糖,还是我困惑?

module Cat FURRY_LEVEL = 4 def self.sound %w{meow purr hiss zzzz}.sample end end puts Cat.sound # This works. puts Cat::sound # This also works. Why?! puts Cat.FURRY_LEVEL # Expected error occurs here. puts Cat::FURRY_LEVEL # This works. 

恒定分辨率始终要求您使用::

方法调用是惯用的,通常是句点( . ),但::也是合法的。 这不仅适用于所谓的模块方法,而是适用于调用任何对象的任何方法:

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

它不是“语法糖”,因为它只是替代语法,例如使用换行符, then换行符,或者只是thenifcase语句的能力。

它是特别允许的,因为Ruby允许使用与常量同名的方法,有时候认为它们是同一个项是有意义的:

 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) #=> # (instance result from method call) 

你可以在Nokogiri库中看到这个,它有(例如) Nokogiri::XML模块以及Nokogiri.XML方法。 在创建XML文档时,许多人选择编写

 @doc = Nokogiri::XML( my_xml ) 

您也可以在Sequel库中看到这一点,您可以在其中编写:

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

同样,我们有一个方法(Sequel.Model)命名为常量(Sequel :: Model) 。 第二行也可以写成

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

......但它看起来并不那么好。

::被称为scope resolution operator ,用于找出定义method, class or constant scope

在下面的示例中,我们使用::来访问在模块ActiveRecord下定义的类Base

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

我们使用::来访问模块中定义的常量

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

这个. operator用于调用module method (用self定义)。

总结:尽管::. 在这里做同样的工作,它用于不同的目的。 您可以从这里阅读更多内容。