The visibility issue is quite confusing.
See the following example.
X = "top-level"
class C
X = "class-level"
class << self
def a
puts X
end
end
end
def C.b
puts X
end
class << C
p [self, self.ancestors] #=> [#<Class:C>, [Class, Module, Object, Kernel]]
def c
puts X
end
end
C.a #=>class-level
C.b #=>top-level
C.c #=>top-level
class D
X = "class-level"
def f
puts X
end
end
obj = D.new
def obj.g
puts X
end
class << obj
p [self, self.ancestors] #=> [#<Class:#<D:0xb7f3bda0>>, [D, Object, Kernel]]
def h
puts X
end
end
obj.f #=>class-level
obj.g #=>top-level
obj.h #=>class-level
Very inconsistent between a class and an object.
Can somebody explain this strange behavior?
Well it's not inconsistent, it's just complicated ![:wink: :wink:](https://emoji.discourse-cdn.com/twitter/wink.png?v=12)
As you can see above for C.c the singleton class of C (#<Class:C>) is asked for the constant, it doesn't have C in it's ancestors, so the constant lookup finds Object's X.
For obj.h the singleton class of obj (#<Class:#<D:0xb7f3bda0>>) is asked for the constant, it does have D in it's ancestors, so D::X is found.
But actually it's even more complicated (continuing your code):
$obj=obj
class Object
class << $obj
def i
puts X
end
end
end
obj.i #=>top-level
This is because the constant lookup first checks in all the outer lexical scopes if the constant is directly defined in one of the classes and then does a full const_get on the innermost class. So in this case, the following happens:
1. Does #<Class:#<D:0xb7f3bda0>> (without ancestors) have a constant X => no
2. Does Object (without ancestors) have a constant X => yes => constant found
If step 2 wouldn't have found the constant then ruby would have checked the ancestors of #<Class:#<D:0xb7f3bda0>> for the constant:
class D
Y = "D::Y"
end
class Object
class << $obj
def j
puts Y
end
end
end
obj.j #=>D::Y
Here the following happens:
1. Does #<Class:#<D:0xb7f3bda0>> (without ancestors) have a constant Y => no
2. Does Object (without ancestors) have a constant Y => no
3. Does #<Class:#<D:0xb7f3bda0>> (including ancestors) have a constant Y => yes => constant found
I hope that helps,
Dominik
···
On Sun, 05 Mar 2006 05:18:39 +0100, Sam Kong <sam.s.kong@gmail.com> wrote: