From: Dominik Bathon Date: 2006-03-05T23:15:26+09:00 Subject: Re: Class method in singleton_methods? On Sun, 05 Mar 2006 05:18:39 +0100, Sam Kong wrote: > 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, 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] #=> [#>, [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 ;-) As you can see above for C.c the singleton class of 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 (#>) 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 #> (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 #> 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 #> (without ancestors) have a constant Y => no 2. Does Object (without ancestors) have a constant Y => no 3. Does #> (including ancestors) have a constant Y => yes => constant found I hope that helps, Dominik