2011-10-19 20 views
35

Więc Module mogą być wykorzystywane w celu zapewnienia przestrzeni nazw Ruby oprócz wstawek, a więc:Jaka jest różnica między tymi konwencjami przestrzeni nazw Ruby?

module SomeNamespace 
    class Animal 

    end 
end 

animal = SomeNamespace::Animal.new 

Ale ja też widziałem następujące zastosowanie:

module SomeNamespace 
end 

class SomeNamespace::Animal 

end 

animal = SomeNamespace::Animal.new 

Moje pytanie brzmi, jak oni jest inny (jeśli są) i który jest bardziej idiomatyczny?

Odpowiedz

37

Różnica polega na zagnieżdżaniu.

W poniższym przykładzie widać, że pierwsza metoda wykorzystująca klasę Foo może uzyskać stałe zmienne BAR_A zakresu zewnętrznego bez błędów.

Tymczasem klasa Baz będzie bombardować błędem niezainicjowanej stałej A :: B :: Baz :: BAR_A. Ponieważ nie wprowadza bezpośrednio A :: *, tylko A :: B :: * jawnie.

module A 
    BAR_A = 'Bar A!' 
    module B 
    BAR_B = 'Bar B!' 
     class Foo 
     p BAR_A 
     p BAR_B 
     end 
    end 
end 

class A::B::Baz 
    p BAR_A 
    p BAR_B 
end 

Oba zachowania mają swoje miejsce. W mojej opinii nie ma prawdziwego konsensusu co do tego, która z nich jest Jedyną Prawdziwą Rubinową Drogą (tm). Ja osobiście używam tego pierwszego, przez większość czasu.

5

Jedyna różnica między tymi dwoma podejściami polega na tym, że druga z nich rzuci uninitialized constant Object::SomeNamespace, jeśli przestrzeń nazw nie została wcześniej zadeklarowana.

Po zadeklarowaniu w jednym pliku, wybrałbym pierwszy, ponieważ nie trzeba powtarzać SomeNamespace.

Przy zastosowaniu wielu plików Używam również drugi, aby uniknąć wyczerpania się następujący problem:

# in a.rb 
require 'b' 

module SomeNamespace 
    def self.animal 
    Animal.new 
    end 
end 

# in b.rb 
class SomeNamespace::Animal 

end 

# irb 
require 'a' # explodes with the uninitialized constant error 

Ten przykład może być wymyślone, ale łatwo go wywołać, jeśli baza kodu jest trochę większy. Zwykle używam metody jawnej (twojej pierwszej), aby tego uniknąć.

Jedną z rzeczy, które mogą być pomocne przy korzystaniu z drugiego formularza, jest wykrywanie literówek w przestrzeni nazw.

Wygląda na to, że nie ma ustalonego sposobu tworzenia przestrzeni nazw. Na przykład Devise łączy oba podejścia: first one, second one.

Powiązane problemy