# Metaclasses

**URL:** <https://www.ruby-forum.com/t/metaclasses/119578>\
**Category:** Ruby\
**Created:** [November 8, 2007, 4:47am UTC](https://www.ruby-forum.com/t/metaclasses/119578 "2007-11-08T04:47:14Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![chunkyslink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f0a364/32.png) [@chunkyslink](https://www.ruby-forum.com/u/chunkyslink)\
**Post date:** [November 8, 2007, 4:47am UTC](https://www.ruby-forum.com/t/metaclasses/119578/1 "2007-11-08T04:47:14Z")

</div>

Hi, all. I’m trying to understand chapter 24 of Programming Ruby.  
I’m using “metaid.rb” from why the lucky stiff’s site to help with the  
examples.  
([http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html](http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html))

Everything is pretty straightforward except for the diagrams of  
inheritance of metaclasses. Figure 24.2 indicates that for a direct  
subclass of Object, its metaclass’s superclass should be Object’s  
metaclass. When I try this out in irb, I don’t get the expected  
result.

$ irb -r metaid  
irb(main):001:0\> String.metaclass  
=\> #Class:String  
irb(main):002:0\> String.metaclass.superclass  
=\> #Class:Class  
irb(main):003:0\> String.metaclass.superclass == Object.metaclass  
=\> false

Surprisingly, when I try it in JRuby, I do get the expected result.

$ jirb -r metaid  
irb(main):001:0\> String.metaclass  
=\> #Class:String  
irb(main):002:0\> String.metaclass.superclass  
=\> #Class:Object  
irb(main):003:0\> String.metaclass.superclass == Object.metaclass  
=\> true

Also, figure 24.3 suggests that for an instance of String, the  
metaclass should be a virtual class extending String itself.

Once again only JRuby produces the expected result.

$ irb -r metaid  
irb(main):001:0\> String.new.metaclass.superclass == String  
=\> false

$ jirb -r metaid  
irb(main):001:0\> String.new.metaclass.superclass == String  
=\> true

Something else I found weird is that when I go up the inheritance of a  
String instance’s metaclass in plain ruby, I quickly run into a loop:

$ irb -r metaid  
irb(main):001:0\> c = String.new.metaclass.superclass.superclass  
=\> #Class:Class  
irb(main):002:0\> c == c.superclass  
=\> true

Any help in understanding this would be greatly appreciated!

Thanks

Neil

---

<div class="post-metadata">

**Author:** ![chunkyslink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f0a364/32.png) [@chunkyslink](https://www.ruby-forum.com/u/chunkyslink)\
**Post date:** [November 8, 2007, 5:31am UTC](https://www.ruby-forum.com/t/metaclasses/119578/2 "2007-11-08T05:31:39Z")

</div>

The JRuby discrepancies are very interesting and I don’t know the  
answer. I e-mailed Charlie Nutter from JRuby and hopefully he’ll chime  
in.

> Something else I found weird is that when I go up the inheritance of a  
> String instance’s metaclass in plain ruby, I quickly run into a loop:
> 
> $ irb -r metaid  
> irb(main):001:0\> c = String.new.metaclass.superclass.superclass  
> =\> #Class:Class  
> irb(main):002:0\> c == c.superclass  
> =\> true
> 
> Any help in understanding this would be greatly appreciated!

This part at least I can explain. I think.

In metaid.rb:

def metaclass; class \<\< self; self; end; end

This means that when you use this method, you’re just having the  
object open up its class and return that to you. What you’re running  
into isn’t really a loop so much as a fundamental particle. In the  
universe it may be true that you can subdivide any particle into  
smaller, “more fundamental” particles, but programming languages are  
much tidier than infinity, and sooner or later you get to the first  
turtle, and after that it’s turtles all the way down. (I’m assuming  
you can understand me, and if you’re using \_why’s guide to Ruby,  
there’s a good chance I sound perfectly rational.) In real life every  
turtle is made up of smaller turtles; inside a programming language,  
when you hit the turtle, you’re there.

In a nutshell, I believe this means that just as the topmost class is  
Object, the topmost _class_ is a Class:Class object. If that doesn’t  
help, there’s a simpler way to see it. Object is the fundamental  
class; all objects are ultimately Objects. Metaclasses have a parallel  
hierarchy, and all classes are ultimately instances of a Class:Class  
object - the object you’ve uncovered here. In a sense you’ve  
discovered the Holy Grail of the metaclass shadow world.

(I’d probably be more coherent if I hadn’t just spent about twenty  
minutes reading \_why’s stuff on Shoes.)

–  
Giles B.

Blog: [http://gilesbowkett.blogspot.com](http://gilesbowkett.blogspot.com)  
Portfolio: [http://www.gilesgoatboy.org](http://www.gilesgoatboy.org)  
Tumblelog: [http://giles.tumblr.com/](http://giles.tumblr.com/)

---

<div class="post-metadata">

**Author:** ![chunkyslink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f0a364/32.png) [@chunkyslink](https://www.ruby-forum.com/u/chunkyslink)\
**Post date:** [November 8, 2007, 12:19pm UTC](https://www.ruby-forum.com/t/metaclasses/119578/3 "2007-11-08T12:19:22Z")

</div>

Hi –

On Thu, 8 Nov 2007, Neil C. wrote:

> $ irb -r metaid  
> irb(main):001:0\> String.metaclass  
> =\> #Class:String  
> irb(main):002:0\> String.metaclass.superclass  
> =\> #Class:Object  
> irb(main):003:0\> String.metaclass.superclass == Object.metaclass  
> =\> true

It actually depends which version of Ruby you use. The superclass  
thing worked as expected in 1.8.2; then it stopped working (I’m not  
sure why); and in 1.9 it’s working again. (“Not working” doesn’t mean  
that the subclasses couldn’t call the methods defined in their  
superclasses’ singleton classes, just that the superclass thing itself  
was not in place.)

$ cat super.rb  
class Object  
def singleton\_class  
class \<\< self; self; end  
end  
end

p String.singleton\_class.superclass == Object.singleton\_class

$ /usr/local/lib/ruby-1.8.2/bin/ruby -v super.rb  
ruby 1.8.2 (2004-12-25) [i686-linux]  
true  
$ ruby -v super.rb  
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-linux]  
false  
$ /usr/local/lib/ruby-svn/bin/ruby -v super.rb  
ruby 1.9.0 (2007-11-07 patchlevel 0) [i686-linux]  
true

David

---

<div class="post-metadata">

**Author:** ![chunkyslink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f0a364/32.png) [@chunkyslink](https://www.ruby-forum.com/u/chunkyslink)\
**Post date:** [November 8, 2007, 12:50pm UTC](https://www.ruby-forum.com/t/metaclasses/119578/4 "2007-11-08T12:50:23Z")

</div>

On 11/8/07, David A. Black [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> It actually depends which version of Ruby you use. The superclass  
> thing worked as expected in 1.8.2; then it stopped working (I’m not  
> sure why); and in 1.9 it’s working again. (“Not working” doesn’t mean  
> that the subclasses couldn’t call the methods defined in their  
> superclasses’ singleton classes, just that the superclass thing itself  
> was not in place.)

interesting, I didn’t realize that this had changed in 1.9.

Actually, it’s not that anything isn’t in place in 1.8, it’s that the  
implementation of Class#superclass skips classes in the superclass  
chain, the same way that Object#class skips an instance singleton  
class if there is one, and the ancestors methods replaces the wrapper  
IClass nodes used to represent included modules in the behavior chain  
of an object into the modules themselves in the result.

It’s smoke and mirrors, and in the case of Ruby 1.9 it seems theres a  
little less smoke and mirrors in Class#superclass.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![chunkyslink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f0a364/32.png) [@chunkyslink](https://www.ruby-forum.com/u/chunkyslink)\
**Post date:** [November 8, 2007, 6:27am UTC](https://www.ruby-forum.com/t/metaclasses/119578/5 "2007-11-08T06:27:10Z")

</div>

On Nov 7, 8:46 pm, Neil C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hi, all. I’m trying to understand chapter 24 of Programming Ruby.  
> I’m using “metaid.rb” from why the lucky stiff’s site to help with the  
> examples. ([http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html](http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html))
> 
> Everything is pretty straightforward except for the diagrams of  
> inheritance of metaclasses. Figure 24.2 indicates that for a direct  
> subclass of Object, its metaclass’s superclass should be Object’s  
> metaclass. When I try this out in irb, I don’t get the expected  
> result.

Possibly this diagram will help:  
[![](http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png) ](http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png)

---

<div class="post-metadata">

**Author:** ![chunkyslink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f0a364/32.png) [@chunkyslink](https://www.ruby-forum.com/u/chunkyslink)\
**Post date:** [November 8, 2007, 12:55pm UTC](https://www.ruby-forum.com/t/metaclasses/119578/6 "2007-11-08T12:55:06Z")

</div>

On Nov 8, 2007, at 12:42 PM, Rick DeNatale wrote:

> interesting, I didn’t realize that this had changed in 1.9.
> 
> Actually, it’s not that anything isn’t in place in 1.8, it’s that the  
> implementation of Class#superclass skips classes in the superclass  
> chain, the same way that Object#class skips an instance singleton  
> class if there is one,

Singleton classes are created on-demand behind the scenes?

– fxn

---

<div class="post-metadata">

**Author:** ![chunkyslink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f0a364/32.png) [@chunkyslink](https://www.ruby-forum.com/u/chunkyslink)\
**Post date:** [November 8, 2007, 1:33pm UTC](https://www.ruby-forum.com/t/metaclasses/119578/7 "2007-11-08T13:33:17Z")

</div>

On 11/8/07, Xavier N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Nov 8, 2007, at 12:42 PM, Rick DeNatale wrote:

> > Actually, it’s not that anything isn’t in place in 1.8, it’s that the  
> > implementation of Class#superclass skips classes in the superclass  
> > chain, the same way that Object#class skips an instance singleton  
> > class if there is one,
> 
> Singleton classes are created on-demand behind the scenes?

Yes, at least in 1.8, and I can’t imagine why that would change.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![chunkyslink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f0a364/32.png) [@chunkyslink](https://www.ruby-forum.com/u/chunkyslink)\
**Post date:** [November 8, 2007, 12:56pm UTC](https://www.ruby-forum.com/t/metaclasses/119578/8 "2007-11-08T12:56:53Z")

</div>

Hi –

On Thu, 8 Nov 2007, Rick DeNatale wrote:

> Actually, it’s not that anything isn’t in place in 1.8, it’s that the  
> implementation of Class#superclass skips classes in the superclass  
> chain, the same way that Object#class skips an instance singleton  
> class if there is one, and the ancestors methods replaces the wrapper  
> IClass nodes used to represent included modules in the behavior chain  
> of an object into the modules themselves in the result.

By “superclass thing itself not in place” I just meant that you get  
false when you ask whether C’s singleton class is the superclass of  
D’s singleton class. So any documentation/books/etc. that describe it  
that way will seem wrong if you try it out in 1.8.6.

> It’s smoke and mirrors, and in the case of Ruby 1.9 it seems theres a  
> little less smoke and mirrors in Class#superclass.

Always a good sign 🙂

David
