# Class method in singleton\_methods?

**URL:** <https://rubytalk.org/t/class-method-in-singleton-methods/25357>\
**Category:** ruby-talk\
**Created:** [2 March 2006 04:43 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357 "2006-03-02T04:43:36Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Minkoo](https://avatars.discourse-cdn.com/v4/letter/m/db5fbb/32.png) [@Minkoo](https://rubytalk.org/u/Minkoo)\
**Post date:** [2 March 2006 04:43 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357/1 "2006-03-02T04:43:36Z")

</div>

Hi group.

I've found that I have to query class methods like:

irb(main):001:0\> class Foo  
irb(main):002:1\> def Foo.bar  
irb(main):003:2\> end  
irb(main):004:1\> end  
=\> nil  
irb(main):005:0\> Foo.singleton\_methods  
=\> ["bar"]  
irb(main):006:0\>

It is interesting that a class method is actually a singleton method. I  
know that there are tons of posting regarding metaclasses/objects.  
Unfortunately, there are simply too many to read and understand all of  
them. So, please forgive my naive question.

Here's the thing. I guess Foo is actually defined like:

irb(main):001:0\> Foo = Class.new  
=\> Foo  
irb(main):002:0\> class \<\< Foo  
irb(main):003:1\> def Foo.bar  
irb(main):004:2\> end  
irb(main):005:1\> end  
=\> nil  
irb(main):006:0\> Foo.singleton\_methods  
=\> ["bar"]  
irb(main):007:0\>

Am I correct?

Sincerely,  
Minkoo Seo

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [2 March 2006 14:07 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357/2 "2006-03-02T14:07:08Z")

</div>

Hi --

> Hi group.
> 
> I've found that I have to query class methods like:
> 
> irb(main):001:0\> class Foo  
> irb(main):002:1\> def Foo.bar  
> irb(main):003:2\> end  
> irb(main):004:1\> end  
> =\> nil  
> irb(main):005:0\> Foo.singleton\_methods  
> =\> ["bar"]  
> irb(main):006:0\>
> 
> It is interesting that a class method is actually a singleton method. I  
> know that there are tons of posting regarding metaclasses/objects.  
> Unfortunately, there are simply too many to read and understand all of  
> them. So, please forgive my naive question.
> 
> Here's the thing. I guess Foo is actually defined like:
> 
> irb(main):001:0\> Foo = Class.new  
> =\> Foo  
> irb(main):002:0\> class \<\< Foo  
> irb(main):003:1\> def Foo.bar  
> irb(main):004:2\> end  
> irb(main):005:1\> end  
> =\> nil  
> irb(main):006:0\> Foo.singleton\_methods  
> =\> ["bar"]  
> irb(main):007:0\>
> 
> Am I correct?

A class method is indeed a singleton method of a Class object. The  
term "class method" is really just a convenient label for this case,  
because it occurs quite frequently.

The "def obj.meth" and "class \<\< obj; def meth" techniques differ as  
to the visibility of constants:

&nbsp;&nbsp;&nbsp;X = 1  
&nbsp;&nbsp;&nbsp;class C  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;X = 2  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def self.a  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;class \<\< C  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def b  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;C.a # 2 (C::X)  
&nbsp;&nbsp;&nbsp;C.b # 1 (top-level X)

But in the vast majority of cases you can use them pretty much  
interchangeably.

David

> **···**
>
> On Thu, 2 Mar 2006, Minkoo Seo wrote:
> 
> --  
> David A. Black (dblack@wobblini.net)  
> Ruby Power and Light ([http://www.rubypowerandlight.com](http://www.rubypowerandlight.com))
> 
> "Ruby for Rails" chapters now available  
> from Manning Early Access Program! [Ruby for Rails](http://www.manning.com/books/black)

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [2 March 2006 14:13 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357/3 "2006-03-02T14:13:34Z")

</div>

Hi --

Adding something to my previous reply:

> Hi --

[...]

> > It is interesting that a class method is actually a singleton method. I  
> > know that there are tons of posting regarding metaclasses/objects.  
> > Unfortunately, there are simply too many to read and understand all of  
> > them. So, please forgive my naive question.

[...]

> > Am I correct?
> 
> A class method is indeed a singleton method of a Class object. The  
> term "class method" is really just a convenient label for this case,  
> because it occurs quite frequently.

The one way in which class methods differ from other singleton methods  
is that they're the only case, as far as I know, where more than one  
object can call a specific singleton method:

&nbsp;&nbsp;&nbsp;class C  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def self.x  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;class D \< C  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;D.x # OK, because D is a subclass of C, even though x is  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# a singleton method on another object (C)

The reason is this: C's singleton class (or "metaclass", as singleton  
classes of Class objects are sometimes known) is the superclass of D's  
singleton class. Since the method x resides in C's singleton class,  
it is visible to instances of that singleton class (namely C), and to  
instances of descendants of that singleton class (namely, D).

In other words, when you send the message "x" to D, D looks in its  
singleton class, and then in the superclass of its singleton class --  
and there it finds a method "x", and executes it.

David

> **···**
>
> On Thu, 2 Mar 2006, dblack@wobblini.net wrote:
> 
> > On Thu, 2 Mar 2006, Minkoo Seo wrote:
> 
> --  
> David A. Black (dblack@wobblini.net)  
> Ruby Power and Light ([http://www.rubypowerandlight.com](http://www.rubypowerandlight.com))
> 
> "Ruby for Rails" chapters now available  
> from Manning Early Access Program! [Ruby for Rails](http://www.manning.com/books/black)

---

<div class="post-metadata">

**Author:** ![Sam\_Kong](https://avatars.discourse-cdn.com/v4/letter/s/ad7895/32.png) [@Sam\_Kong](https://rubytalk.org/u/Sam_Kong)\
**Post date:** [5 March 2006 04:18 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357/4 "2006-03-05T04:18:39Z")

</div>

dblack@wobblini.net wrote:

> Hi --
> 
> \> Hi group.  
> \>  
> \> I've found that I have to query class methods like:  
> \>  
> \> irb(main):001:0\> class Foo  
> \> irb(main):002:1\> def Foo.bar  
> \> irb(main):003:2\> end  
> \> irb(main):004:1\> end  
> \> =\> nil  
> \> irb(main):005:0\> Foo.singleton\_methods  
> \> =\> ["bar"]  
> \> irb(main):006:0\>  
> \>  
> \> It is interesting that a class method is actually a singleton method. I  
> \> know that there are tons of posting regarding metaclasses/objects.  
> \> Unfortunately, there are simply too many to read and understand all of  
> \> them. So, please forgive my naive question.  
> \>  
> \> Here's the thing. I guess Foo is actually defined like:  
> \>  
> \> irb(main):001:0\> Foo = Class.new  
> \> =\> Foo  
> \> irb(main):002:0\> class \<\< Foo  
> \> irb(main):003:1\> def Foo.bar  
> \> irb(main):004:2\> end  
> \> irb(main):005:1\> end  
> \> =\> nil  
> \> irb(main):006:0\> Foo.singleton\_methods  
> \> =\> ["bar"]  
> \> irb(main):007:0\>  
> \>  
> \> Am I correct?
> 
> A class method is indeed a singleton method of a Class object. The  
> term "class method" is really just a convenient label for this case,  
> because it occurs quite frequently.
> 
> The "def obj.meth" and "class \<\< obj; def meth" techniques differ as  
> to the visibility of constants:
> 
> &nbsp;&nbsp;&nbsp;X = 1  
> &nbsp;&nbsp;&nbsp;class C  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;X = 2  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def self.a  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;class \<\< C  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def b  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;C.a # 2 (C::X)  
> &nbsp;&nbsp;&nbsp;C.b # 1 (top-level X)

The visibility issue is quite confusing.  
See the following example.

X = "top-level"

class C  
&nbsp;&nbsp;X = "class-level"

&nbsp;&nbsp;class \<\< self  
&nbsp;&nbsp;&nbsp;&nbsp;def a  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
end

def C.b  
&nbsp;&nbsp;puts X  
end

class \<\< C  
&nbsp;&nbsp;def c  
&nbsp;&nbsp;&nbsp;&nbsp;puts X  
&nbsp;&nbsp;end  
end

C.a #=\>class-level  
C.b #=\>top-level  
C.c #=\>top-level

class D  
&nbsp;&nbsp;X = "class-level"  
&nbsp;&nbsp;def f  
&nbsp;&nbsp;&nbsp;&nbsp;puts X  
&nbsp;&nbsp;end  
end

obj = D.new

def obj.g  
&nbsp;&nbsp;puts X  
end

class \<\< obj  
&nbsp;&nbsp;def h  
&nbsp;&nbsp;&nbsp;&nbsp;puts X  
&nbsp;&nbsp;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?

Thanks.  
Sam

> **···**
>
> > On Thu, 2 Mar 2006, Minkoo Seo wrote:

---

<div class="post-metadata">

**Author:** ![Dominik\_Bathon](https://avatars.discourse-cdn.com/v4/letter/d/67e7ee/32.png) [@Dominik\_Bathon](https://rubytalk.org/u/Dominik_Bathon)\
**Post date:** [5 March 2006 14:15 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357/5 "2006-03-05T14:15:26Z")

</div>

> The visibility issue is quite confusing.  
> See the following example.
> 
> X = "top-level"
> 
> class C  
> &nbsp;&nbsp;X = "class-level"
> 
> &nbsp;&nbsp;class \<\< self  
> &nbsp;&nbsp;&nbsp;&nbsp;def a  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end  
> end
> 
> def C.b  
> &nbsp;&nbsp;puts X  
> end
> 
> class \<\< C

&nbsp;&nbsp;p [self, self.ancestors] #=\> [#\<Class:C\>, [Class, Module, Object, Kernel]]

> &nbsp;&nbsp;def c  
> &nbsp;&nbsp;&nbsp;&nbsp;puts X  
> &nbsp;&nbsp;end  
> end
> 
> C.a #=\>class-level  
> C.b #=\>top-level  
> C.c #=\>top-level
> 
> class D  
> &nbsp;&nbsp;X = "class-level"  
> &nbsp;&nbsp;def f  
> &nbsp;&nbsp;&nbsp;&nbsp;puts X  
> &nbsp;&nbsp;end  
> end
> 
> obj = D.new
> 
> def obj.g  
> &nbsp;&nbsp;puts X  
> end
> 
> class \<\< obj

&nbsp;&nbsp;p [self, self.ancestors] #=\> [#\<Class:#\<D:0xb7f3bda0\>\>, [D, Object, Kernel]]

> &nbsp;&nbsp;def h  
> &nbsp;&nbsp;&nbsp;&nbsp;puts X  
> &nbsp;&nbsp;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 (#\<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  
&nbsp;&nbsp;class \<\< $obj  
&nbsp;&nbsp;&nbsp;&nbsp;def i  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;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  
&nbsp;&nbsp;Y = "D::Y"  
end

class Object  
&nbsp;&nbsp;class \<\< $obj  
&nbsp;&nbsp;&nbsp;&nbsp;def j  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts Y  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;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:

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [5 March 2006 19:01 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357/6 "2006-03-05T19:01:49Z")

</div>

Hi --

> But actually it's even more complicated (continuing your code):
> 
> $obj=obj  
> class Object  
> &nbsp;&nbsp;class \<\< $obj  
> &nbsp;&nbsp;&nbsp;&nbsp;def i  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;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  
> &nbsp;&nbsp;Y = "D::Y"  
> end
> 
> class Object  
> &nbsp;&nbsp;class \<\< $obj  
> &nbsp;&nbsp;&nbsp;&nbsp;def j  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts Y  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;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

But Object is always an ancestor, so you don't need step 2. Also,  
step 2 (lookup in Object) doesn't really happen second; for example,  
if you put yourself in D context, the lookup will hit D::X before it  
hits Object:❌

$obj=obj  
class Object  
&nbsp;&nbsp;&nbsp;class D  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class \<\< $obj  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def k  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end  
end

obj.k # class-level

So the resolution path is:

&nbsp;&nbsp;&nbsp;#\<Class:#\<D...\>\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D # X found here  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object # X exists here but not reached

As I understand it, some of this is determined quasi-statically...  
though not the singleton class parts, since those can't be determined  
at all until runtime.

David

> **···**
>
> On Sun, 5 Mar 2006, Dominik Bathon wrote:
> 
> --  
> David A. Black (dblack@wobblini.net)  
> Ruby Power and Light ([http://www.rubypowerandlight.com](http://www.rubypowerandlight.com))
> 
> "Ruby for Rails" chapters now available  
> from Manning Early Access Program! [http://www.manning.com/books/black](http://www.manning.com/books/black)

---

<div class="post-metadata">

**Author:** ![Sam\_Kong](https://avatars.discourse-cdn.com/v4/letter/s/ad7895/32.png) [@Sam\_Kong](https://rubytalk.org/u/Sam_Kong)\
**Post date:** [6 March 2006 20:58 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357/7 "2006-03-06T20:58:40Z")

</div>

Dominik Bathon wrote:

> **···**
>
> > On Sun, 05 Mar 2006 05:18:39 +0100, Sam Kong \<sam.s.kong@gmail.com\> 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  
> > &nbsp;&nbsp;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  
> > &nbsp;&nbsp;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 😉
> > 
> > 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  
> > &nbsp;&nbsp;class \<\< $obj  
> > &nbsp;&nbsp;&nbsp;&nbsp;def i  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;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  
> > &nbsp;&nbsp;Y = "D::Y"  
> > end
> > 
> > class Object  
> > &nbsp;&nbsp;class \<\< $obj  
> > &nbsp;&nbsp;&nbsp;&nbsp;def j  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts Y  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;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,
> 
> Yes. That helps a lot.  
> Thank you very much.
> 
> Sam

---

<div class="post-metadata">

**Author:** ![Dominik\_Bathon](https://avatars.discourse-cdn.com/v4/letter/d/67e7ee/32.png) [@Dominik\_Bathon](https://rubytalk.org/u/Dominik_Bathon)\
**Post date:** [5 March 2006 19:59 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357/8 "2006-03-05T19:59:41Z")

</div>

> Hi --
> 
> > class D  
> > &nbsp;&nbsp;Y = "D::Y"  
> > end
> > 
> > class Object  
> > &nbsp;&nbsp;class \<\< $obj  
> > &nbsp;&nbsp;&nbsp;&nbsp;def j  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts Y  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;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
> 
> But Object is always an ancestor, so you don't need step 2.

Yes, but these are the steps that ruby (1.8.4) does when looking up the constants, here is the code (eval.c):

static VALUE  
ev\_const\_get(cref, id, self)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NODE \*cref;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ID id;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VALUE self;  
{  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NODE \*cbase = cref;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VALUE result;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while (cbase && cbase-\>nd\_next) {  
&nbsp;&nbsp;VALUE klass = cbase-\>nd\_clss;

&nbsp;&nbsp;if (NIL\_P(klass)) return rb\_const\_get(CLASS\_OF(self), id);  
&nbsp;&nbsp;while (RCLASS(klass)-\>iv\_tbl && st\_lookup(RCLASS(klass)-\>iv\_tbl, id, &result)) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (result == Qundef) {  
&nbsp;&nbsp;&nbsp;&nbsp;if (!RTEST(rb\_autoload\_load(klass, id))) break;  
&nbsp;&nbsp;&nbsp;&nbsp;continue;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return result;  
&nbsp;&nbsp;}  
&nbsp;&nbsp;cbase = cbase-\>nd\_next;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return rb\_const\_get(cref-\>nd\_clss, id);  
}

The while loop checks if the constant is defined directly (without ancestors) in one of the enclosing classes, and finally if the while loop doesn't find the constant ruby does a full rb\_const\_get() on the innermost class (which includes the ancestors).

> Also,  
> step 2 (lookup in Object) doesn't really happen second; for example,  
> if you put yourself in D context, the lookup will hit D::X before it  
> hits Object:❌
> 
> $obj=obj  
> class Object  
> &nbsp;&nbsp;&nbsp;class D  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class \<\< $obj  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def k  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;end  
> end
> 
> obj.k # class-level
> 
> So the resolution path is:
> 
> &nbsp;&nbsp;&nbsp;#\<Class:#\<D...\>\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D # X found here  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object # X exists here but not reached

In this case yes, but that doesn't contradict what I said.

> As I understand it, some of this is determined quasi-statically...  
> though not the singleton class parts, since those can't be determined  
> at all until runtime.

You can think of it as happening "quasi-statically", but actually class, module and "class \<\<" are executed almost identically by the interpreter (only different "preparations").

Dominik

> **···**
>
> On Sun, 05 Mar 2006 20:01:49 +0100, \<dblack@wobblini.net\> wrote:
> 
> > On Sun, 5 Mar 2006, Dominik Bathon wrote:

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [5 March 2006 20:15 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357/9 "2006-03-05T20:15:09Z")

</div>

Hi --

> > Hi --
> > 
> > > class D  
> > > &nbsp;&nbsp;Y = "D::Y"  
> > > end
> > > 
> > > class Object  
> > > &nbsp;&nbsp;class \<\< $obj  
> > > &nbsp;&nbsp;&nbsp;&nbsp;def j  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts Y  
> > > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > > &nbsp;&nbsp;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
> > 
> > But Object is always an ancestor, so you don't need step 2.
> 
> Yes, but these are the steps that ruby (1.8.4) does when looking up the constants, here is the code (eval.c):
> 
> static VALUE  
> ev\_const\_get(cref, id, self)  
> &nbsp;&nbsp;NODE \*cref;  
> &nbsp;&nbsp;ID id;  
> &nbsp;&nbsp;VALUE self;  
> {  
> &nbsp;&nbsp;NODE \*cbase = cref;  
> &nbsp;&nbsp;VALUE result;
> 
> &nbsp;&nbsp;while (cbase && cbase-\>nd\_next) {  
> &nbsp;&nbsp;VALUE klass = cbase-\>nd\_clss;
> 
> &nbsp;&nbsp;if (NIL\_P(klass)) return rb\_const\_get(CLASS\_OF(self), id);  
> &nbsp;&nbsp;while (RCLASS(klass)-\>iv\_tbl && st\_lookup(RCLASS(klass)-\>iv\_tbl, id, &result)) {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (result == Qundef) {  
> &nbsp;&nbsp;&nbsp;&nbsp;if (!RTEST(rb\_autoload\_load(klass, id))) break;  
> &nbsp;&nbsp;&nbsp;&nbsp;continue;  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return result;  
> &nbsp;&nbsp;}  
> &nbsp;&nbsp;cbase = cbase-\>nd\_next;  
> &nbsp;&nbsp;}  
> &nbsp;&nbsp;return rb\_const\_get(cref-\>nd\_clss, id);  
> }
> 
> The while loop checks if the constant is defined directly (without ancestors) in one of the enclosing classes, and finally if the while loop doesn't find the constant ruby does a full rb\_const\_get() on the innermost class (which includes the ancestors).

I think I was misunderstanding the relation between your example and  
your explanation. If I'm (now) right, you were just using Object as  
an example of an enclosing class. I had thought you were saying that  
Object itself always gets checked before the ancestors.

> > As I understand it, some of this is determined quasi-statically...  
> > though not the singleton class parts, since those can't be determined  
> > at all until runtime.
> 
> You can think of it as happening "quasi-statically", but actually class, module and "class \<\<" are executed almost identically by the interpreter (only different "preparations").

I mean constant resolution specifically. But I may be behind the  
times.

David

> **···**
>
> On Mon, 6 Mar 2006, Dominik Bathon wrote:
> 
> > On Sun, 05 Mar 2006 20:01:49 +0100, \<dblack@wobblini.net\> wrote:
> > 
> > > On Sun, 5 Mar 2006, Dominik Bathon wrote:
> 
> --  
> David A. Black (dblack@wobblini.net)  
> Ruby Power and Light ([http://www.rubypowerandlight.com](http://www.rubypowerandlight.com))
> 
> "Ruby for Rails" chapters now available  
> from Manning Early Access Program! [Ruby for Rails](http://www.manning.com/books/black)

---

<div class="post-metadata">

**Author:** ![Dominik\_Bathon](https://avatars.discourse-cdn.com/v4/letter/d/67e7ee/32.png) [@Dominik\_Bathon](https://rubytalk.org/u/Dominik_Bathon)\
**Post date:** [5 March 2006 21:37 UTC](https://rubytalk.org/t/class-method-in-singleton-methods/25357/10 "2006-03-05T21:37:25Z")

</div>

> I think I was misunderstanding the relation between your example and  
> your explanation. If I'm (now) right, you were just using Object as  
> an example of an enclosing class. I had thought you were saying that  
> Object itself always gets checked before the ancestors.

I used Object because the top-level X is stored in Object and I wanted to show that there is a (maybe surprising) difference between:

class \<\< obj  
&nbsp;&nbsp;def h  
&nbsp;&nbsp;&nbsp;&nbsp;puts X  
&nbsp;&nbsp;end  
end

and

$obj=obj  
class Object  
&nbsp;&nbsp;class \<\< $obj  
&nbsp;&nbsp;&nbsp;&nbsp;def i  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts X  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
end

> **···**
>
> On Sun, 05 Mar 2006 21:15:09 +0100, \<dblack@wobblini.net\> wrote:
> 
> > > > As I understand it, some of this is determined quasi-statically...  
> > > > though not the singleton class parts, since those can't be determined  
> > > > at all until runtime.
> > > 
> > > You can think of it as happening "quasi-statically", but actually class, module and "class \<\<" are executed almost identically by the interpreter (only different "preparations").
> > 
> > I mean constant resolution specifically. But I may be behind the  
> > times.
> > 
> > David
