On Jun 1, 2013, at 5:35 PM, jin chizhong [email protected] wrote:
When I use a dynamic class, It can not reference constants.
See follow code and remark.
The reason is that your two examples have different lexical scopes and
constants are resolved lexically.
class T
def hello
puts self.class.constants.join " " # right, AAA
puts AAA # right, 1
end
end
Here, AAA is lexically within T so ruby searches T::AAA and ::AAA before
giving up.
T::AAA = 1
t = T.new
t.hello
You can see this by doing:
class Demo; def get_T; T; end; end
T = ‘top’
Demo.new.get_T # ‘top’
Demo::T = ‘demo’ # now there is ::T and Demo::T
Demo.new.get_T # ‘demo’, because Demo::T is searched before ::T
c = Class.new do
def hello
puts self.class.constants.join " " # right, AAA
puts AAA # error: uninitialized constant AAA (NameError)
end
end
Here AAA is not lexically in a class so ruby only searches ::AAA
before giving up, which is what you see below when you call inst.hello
c::AAA = 123
inst = c.new
inst.hello
If you continue from this point:
puts c::AAA # 123
AAA = 456 # set top level AAA
puts c:AAA # still 123
c.new.hello # 456 because AAA in hello now finds AAA at the top level
scope
I think the key to understanding this is to realize that constant lookup
path is established when the code is parsed and not when the code is
executed.
You asked if there is a way around this and there sort of is. If you
want to force the lookup to start in a particular module then say it
explicitly:
c = Class.new do
def hello
puts self.class.constants.join " " # right, AAA
puts self.class::AAA # forces search to start in c
end
end
Just to be a bit more complete, ruby also searches the superclasses of
any class in the lexical scope:
class A
def lookup_X
X # X is resolved as A::X, ::X
end
end
class B < A
def lookup_X_from_B
X # X is resolved as B::X, A::X, ::X
end
end
A.new.lookup_X # A::X, ::X
B.new.lookup_X # still A::X, ::X even though called on instance
of B
B.new.lookup_X_from_B # B::X, A::X, ::X
Now try setting X = 1; A::X = 2, and B::X = 3 and see what the lookup
methods return.
Gary W.