我读过的文档告诉我使用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.
答案 0 :(得分:9)
恒定分辨率始终要求您使用::
。
方法调用是惯用的,通常是句点(.
),但::
也是合法的。这不仅适用于所谓的模块方法,而是适用于在任何对象上调用任何方法:
class Foo
def bar
puts "hi"
end
end
Foo.new::bar
#=> hi
它不是“语法糖”,因为它只是替代语法,例如使用换行符,if
和换行符编写case
或then
语句的能力,或者只是then
。
这是特别允许的,因为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) #=> #<Foo::Bar:0x2d54fc0 @x=42> (instance result from method call)
您在Nokogiri库中通常会在Ruby中看到这一点,该库具有(例如)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
同样,我们的method (Sequel.Model)与constant (Sequel::Model)的名称相同。第二行也可以写成
class User < Sequel.Model(DB[:regular_users])
......但它看起来并不那么好。
答案 1 :(得分:5)
::
名为scope resolution operator
,用于查找scope
method, class or constant
定义的内容。
在以下示例中,我们使用::
访问模块Base
ActiveRecord
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)
.
运算符用于调用模块的module method
(使用self。定义。)。
摘要:尽管::
和.
在此处执行相同的工作,但它用于不同的目的。您可以从here了解更多信息。