问题
I've been reading this Ruby book, then there's this example that I haven't well understood :
CONST = "outer"
module Mod
CONST = 1
def Mod.method1
# module method
CONST + 1
end
end
module Mod::Inner
def (Mod::Inner).method2
CONST + " scope"
end
end
Mod::CONST # => 1
Mod.method1 # => 2
Mod::Inner::method2 # => "outer scope"
Would you please explain this to me (a detailed explanation) so I can fully understand how the scope works in Ruby. Thank you.
回答1:
Constants in Ruby (identifiers beginning with a capital letter) are accessible based on the lexical scope in which they are defined/accessed.
In method1, the CONST within the Mod scope takes precedence over the outermost CONST. In method2, the CONST within the Mod scope is not visible lexically, so the outermost CONST is accessed.
As for the method definitions themselves, when the name is qualified with a preceding module constant (e.g. Mod or Mod::Inner), the method is defined as a "module method" rather than as an instance method of self.class (the default).
Names in the module/method hierarchy are separated by :: or, alternatively in the case of the separator between the module and the module method, a ..
Update: Note that the reason why Mod's constants are not visible to method2 is that Mod was not separately "opened". The definition skipped directly to Mod::Inner. If the code were changed to:
module Mod
module Inner
def (Mod::Inner).method2
...
Then Mod's constants would be accessible to method2 and take precedence over any in the outer scope.
回答2:
You would find a good explanation on Ruby Constant lookup here
I would share code snippets with some explanation:
CONST = "outer"
module Mod
CONST = 1
def Mod.method1
# module method
Module.nesting # => [Mod]
CONST + 1
end
end
module Mod::Inner
def (Mod::Inner).method2
Module.nesting # => [Mod::Inner]
CONST + " scope"
end
end
Mod::CONST # => 1
Mod.method1 # => 2
Mod::Inner::method2 # => "outer scope"
Have a look at the evaluation of Module.nesting above (Mod::Inner).method2 looks in Mod::Inner as specified in the nesting for CONST which it does not find before it calls the main Object for CONST
In the example I have below, you would see that Mod::Inner.method2 makes a call to Mod::Inner and then Mod to seek for CONST which it finds, so no need to call the CONST in Object
module Mod
CONST = 1
def Mod.method1
Module.nesting # => [Mod]
CONST + 1
end
module Inner
def (Mod::Inner).method2
Module.nesting # => [Mod::Inner, Mod]
CONST.to_s + " scope"
end
end
end
Mod::CONST # => 1
Mod.method1 # => 2
Object::CONST # => "outer"
Mod::Inner::method2 # => "1 scope"
When in doubt use nested class/constant definition over lexical, it would always do the right thing as expected
来源:https://stackoverflow.com/questions/20848123/how-do-modules-resolve-a-constants-scope