2012-02-16 15 views
7

La documentazione che ho letto mi dice di usare Module.method per accedere ai metodi in un modulo. Tuttavia, posso usare anche il metodo Module :: È questo zucchero sintattico, o sono confuso?Accesso ai metodi del modulo con:

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

Non sei confuso: entrambi sono legali. Vedi la mia risposta estesa sotto per il perché. – Phrogz

risposta

9

La risoluzione costante richiede sempre l'utilizzo di ::.

L'invocazione del metodo è idiomatica e di solito un periodo (.), ma anche :: è legale. Questo non è solo vero per i cosiddetti metodi di modulo, ma per invocare un metodo su un oggetto qualsiasi:

class Foo 
    def bar 
    puts "hi" 
    end 
end 

Foo.new::bar 
#=> hi 

Non è tanto "zucchero sintassi" in quanto è la sintassi semplice alternativa, come ad esempio la capacità di scrivere if oppure case dichiarazioni con una nuova riga, then e newline o solo then.

È specificamente consentito perché rubino permette metodi con lo stesso nome di una costante, ed a volte ha senso pensare che siano la stessa voce:

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) 

Vedete questo comunemente in Ruby nel Nokogiri libreria, che ha (ad esempio) il modulo Nokogiri::XML e il metodo Nokogiri.XML. Quando si crea un documento XML, molte persone scelgono di scrivere

@doc = Nokogiri::XML(my_xml) 

Si vede anche questo nella biblioteca Sequel, dove è possibile scrivere sia:

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

Anche in questo caso, abbiamo una method (Sequel.Model) chiamato lo stesso a constant (Sequel::Model). La seconda riga potrebbe anche essere scritta come

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

e hellip, ma non sembra altrettanto bello.

+2

Alcuni metodi comunemente noti come questo sono 'Array',' Float', 'Integer' e' String'. –

+0

@Josh Grandi esempi (anche se personalmente non uso mai, mai, quei metodi :) – Phrogz

+0

solo un sidenote :) "La risoluzione costante richiede sempre che si usi' :: '" per quanto riguarda '# const_get'? – farnoy

5

Il :: è chiamato scope resolution operator, che viene utilizzato per scoprire in quale scope è definito il method, class or constant.

Nel seguente esempio, usiamo :: accedere classe Base che è definita sotto modulo ActiveRecord

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

Usiamo :: accedere costanti definite nel modulo

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

L'operatore . è usato chiamare un module method (definito con self.) di un modulo.

Riepilogo: Anche se entrambi gli apparecchi :: e . eseguono lo stesso lavoro qui, vengono utilizzati per scopi diversi. Puoi leggere di più da here.