2012-02-16 6 views
7

Документация, которую я прочитал, говорит мне использовать Module.method для доступа к методам в модуле. Однако я могу использовать метод Module ::. Является ли этот синтаксический сахар, или я смущен?Доступ к методам модуля с ::

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. 
+1

Вы не смущены: оба являются законными. См. Мой расширенный ответ ниже, почему. – Phrogz

ответ

9

Постоянное разрешение всегда требует использования ::.

Метод вызова идиоматически и обычно период (.), но :: также является законным. Это не только верно для так называемых методов модуля, но для вызова любого метода любого объекта:

class Foo 
    def bar 
    puts "hi" 
    end 
end 

Foo.new::bar 
#=> hi 

Это не так много «синтаксиса», как это просто альтернативный синтаксис, таких как умение писать if или case с помощью новой строки, then и новой строки, или только then.

Это специально допускается, так как рубин позволяет методы с тем же именем, как постоянная, а иногда имеет смысл думать, что они такие же пункт:

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 библиотека, которая имеет (например) модуль 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) названный так же, как a constant (Sequel::Model). Вторая строка также может быть записана как

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

& hellip; но это выглядит не так хорошо.

+2

Некоторые общеизвестные методы, такие как 'Array',' Float', 'Integer' и' String'. –

+0

@ Josh Отличные примеры (хотя я лично никогда, никогда не использую эти методы :) – Phrogz

+0

просто sidenote :) «Постоянное разрешение всегда требует использования' :: '» как насчет '# const_get'? – farnoy

5

Адрес ::scope resolution operator, который используется для определения того, что scopemethod, 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.