2013-07-11 5 views
7

Warum führt das erneute Öffnen eines verschachtelten Moduls je nach verwendeter Syntax zu unterschiedlichen Ergebnissen? Zum Beispiel funktioniert das gut:Erneutes Öffnen der verschachtelten Modulanomalie in Ruby

module A 
    module E 
    end 
end 
module A 
    module E 
    def E.e 
    end 
    end 
end 

Aber:

module A 
    module E 
    end 
end 
module A::E 
    def E.e 
    end 
end 

gibt den Fehler:

reopen.rb:6:in `<module:E>': uninitialized constant A::E::E (NameError) 
from reopen.rb:5:in `<main>' 

(Bevor jemand dies weist darauf hin, eine Abhilfe ist self zu verwenden statt der Modulname beim Definieren von Ee, aber das ist nicht wirklich der Punkt dieses Beitrags.)

+2

Also, was ist die Frage? –

+0

Fairer Punkt - umformuliert. –

Antwort

4

Die module keyword legt einen Namespacekontext fest, der auf Verweise auf vorhandene Modulnamen überprüft wird. Diese Namespaces werden dann von innen nach außen durchsucht, um Verweise auf Modul- (und Klassen-) Namen aufzulösen.

In Ihrem ersten Beispiel, es sieht wie Sie E.e innerhalb module E Block definieren müssen, aber in der Tat Sie dies nicht tun:

module A 
    module E 
    end 
end 
module A 
    def E.e 
    end 
end 

Was in beide Beispiele passiert, ist, dass Ruby schaut der aktuelle Namespace und versucht als Modulname. In beiden Beispielen ist das erste, was es überprüft, nämlich A::E::E, das nicht existiert. Dann fällt es zurück in den nächsten Kontext. Worin unterscheiden sich die Beispiele: Im ersten Beispiel ist es A::E, was gilt, im zweiten Beispiel ist es nur E, was nicht der Fall ist. Der Fehler, der dann ausgelöst wird, bezieht sich auf den ersten Namen, den er überprüft hat.

+1

Interessant. IMO 'Modul A :: E' erstellt einen nicht verschachtelten Kontext mit einem" verschachtelten "Namen ist ein Fehler. Wenn es äquivalent wäre: 'Modul A Modul E ...' Ich würde sagen, das wäre viel näher an die normale Intuition über Namespaces. –

+0

Ja, es erstellt immer einen einzelnen Kontext innerhalb des Modulblocks. In dieser Hinsicht ist es zumindest in sich konsistent. Ich kann keinen Grund sehen, warum es nicht anders gemacht werden könnte, außer aus historischen Gründen - es könnte sogar Code geben, der sich auf das aktuelle Verhalten stützt - wo "E" und "A :: E" beide definiert sind zum Beispiel. –

+0

Fair genug. Wenn Sie das Problem hier ansprechen, könnte dies dazu führen, dass es in eine zukünftige Version von Ruby übergeht. –

Verwandte Themen