2015-12-17 2 views
5

Ich habe mich gerade für eine Weile festgefahren. Nehmen Sie diese Basis:Warum findet Ruby keine Klassen in einem höheren Bereich, wenn das Modul mit ::?

module Top 
    class Test 
    end 

    module Foo 
    end 
end 

Später, ich kann Klassen innerhalb Foo definieren, die Test, indem Sie diese erweitert:

module Top 
    module Foo 
    class SomeTest < Test 
    end 
    end 
end 

Allerdings, wenn ich versuchen Vertiefung zu minimieren, indem :: Verwendung des Moduls angeben:

module Top::Foo 
    class Failure < Test 
    end 
end 

Dies scheitert mit:

NameError: uninitialized constant Top::Foo::Test

Ist dies ein Fehler oder ist es nur eine logische Konsequenz der Art und Weise, wie Ruby Variablennamen auflöst?

Antwort

7

Is this a bug, or is it just a logical consequence

Es ist eine "Marotte". Manche halten es für einen Fehler.

Übergeordnete Bereiche, die zum Nachschlagen nicht aufgelöster Konstanten verwendet werden, werden durch Modulverschachtelung bestimmt. Es passiert einfach, dass wenn Sie module Top::Foo verwenden, es nur eine Ebene der Verschachtelung statt zwei erstellt. Observe:

module Top 
    module Foo 
    class SomeTest 
     Module.nesting # => [Top::Foo::SomeTest, Top::Foo, Top] 
    end 
    end 
end 

module Top::Foo 
    class SomeTest 
    Module.nesting # => [Top::Foo::SomeTest, Top::Foo] 
    end 
end 
+2

Klingt wie ein Fehler zu mir: P Aber sehr informative Antwort, danke – Hubro

+0

Ich würde sagen, halte ich es für einen Fehler, hat jemand einen Fehlerbericht in Ruby dazu gefunden? Ich möchte gerne zur Diskussion beitragen und schauen, was daran beteiligt wäre. –

+0

Hinweis: Es wurde ein Link gefunden, der besagt, dass es beabsichtigt ist [hier] (https://bugs.ruby-lang.org/issues/11705) –

1

Dies wird erwartet. Die Verwendung von :: ändert den Umfang der konstanten Suche und erwartet, dass Test unter Top::Foo definiert wird.

das erwartete Ergebnis zu erhalten, könnten Sie schreiben:

module Top::Foo 
    class SomeTest < Top::Test 
    end 
end 

oder:

module Top 
    class Foo::SomeTest < Test 
    end 
end 

oder sogar:

class Top::Foo::SomeTest < Top::Test 
end 
Verwandte Themen