I understand that all classes in ruby are instances of metaclass Class. And that "regular" objects are instances of these classes (the instances of metaclass Class).
But I keep wondering, I mean classes are root of objects, classes are themselves instances of Class (called metaclass because its instances are classes). I saw in some blogs some overriding of method new
, of class Class.
So Class behaves as a class, but its instances are classes. So it seems we have a circle, it looks likes class Class is an instance of itself.
I'm clearly missing a point here. What is the origin of class Class?
Here's an example that's confusing me:
class Class
def new
#something
end
end
But keyword class
implies an instance of class Class. So how do this work?
Though it is a little out of date, this article by _why may help in understanding the behavior. You can find an even deeper dive into the subject in Paolo Perrotta's Metaprogramming Ruby.
There is a meta-circularity given by the "twist" link. It is the built-in superclass link from the root's eigenclass to the
Class
class. This can be expressed byA clue to understanding the
.class
map is seeing this map as derived from the eigenclass and superclass links: for an objectx
,x.class
is the first class in the superclass chain ofx
's eigenclass. This can be expressed bywhere
eigenclass
is a "conceptual alias" ofsingleton_class
(resistant to issues with immediate values),y.superclass(i)
meansi
-th superclass ofy
andn
is smallest such thatx.eigenclass.superclass(n)
is a class. Equivalently, eigenclasses in the superclass chain ofx.eigenclass
are skipped (see rb_class_real which also reveals that in MRI, evensuperclass
links are implemented indirectly – they arise by skipping "iclasses"). This results in that theclass
of every class (as well as of every eigenclass) is constantly theClass
class.A picture is provided by this diagram.
The metaclass confusion has 2 main sources:
Smalltalk. The Smalltalk-80 object model contains conceptual inconsistencies that are rectified by the Ruby object model. In addition, Smalltalk literature uses dialectics in terminology, which unfortunately has not been sufficiently remedied in the Ruby literature.
The definition of metaclass. At present, the definition states that metaclasses are classes of classes. However, for so called "implicit metaclasses" (the case of Ruby and Smalltalk-80) a much more fitting definition would be that of meta-objects of classes.
Easy: it doesn't. Not in Ruby, anyway.
Just like in most other languages, there are some core entities that are simply assumed to exist. They fall from the sky, materialize out of thin air, magically appear.
In Ruby, some of those magic things are:
Object
doesn't have a superclass, but you cannot define a class with no superclass, the implicit direct superclass is alwaysObject
. [Note: there may be implementation-defined superclasses ofObject
, but eventually, there will be one which doesn't have a superclass.]Object
is an instance ofClass
, which is a subclass ofObject
(which means that indirectlyObject
is an instance ofObject
itself)Class
is a subclass ofModule
, which is an instance ofClass
Class
is an instance ofClass
None of these things can be explained in Ruby.
BasicObject
,Object
,Module
andClass
all need to spring into existence at the same time because they have circular dependencies.Just because this relationship cannot be expressed in Ruby code, doesn't mean the Ruby Language Specification can't say it has to be so. It's up to the implementor to figure out a way to do this. After all, the Ruby implementation has a level of access to the objects that you as a programmer don't have.
For example, the Ruby implementation could first create
BasicObject
, setting both itssuperclass
pointer and itsclass
pointer tonull
.Then, it creates
Object
, setting itssuperclass
pointer toBasicObject
and itsclass
pointer tonull
.Next, it creates
Module
, setting itssuperclass
pointer toObject
and itsclass
pointer tonull
.Lastly, it creates
Class
, setting itssuperclass
pointer toModule
and itsclass
pointer tonull
.Now, we can overwrite
BasicObject
's,Object
's,Module
's, andClass
'sclass
pointer to point toClass
, and we're done.This is easy to do from outside the system, it just looks weird from the inside.
Once they do exist, however, it is perfectly possible to implement most of their behavior in plain Ruby. You only need very barebones versions of those classes, thanks to Ruby's open classes, you can add any missing functionality at a later time.
In your example, the
class Class
is not creating a new class namedClass
, it is reopening the existing classClass
, which was given to us by the runtime environment.So, it is perfectly possible to explain the default behavior of
Class#new
in plain Ruby:[Note: actually,
initialize
is private, so you need to useobj.send(:initialize, *args, &block)
to circumvent the access restriction.]BTW:
Class#allocate
is another one of those magic things. It allocates a new empty object in Ruby's object space, which is something that cannot be done in Ruby. So,Class#allocate
is something that has to be provided by the runtime system as well.Yes, Class is an instance of itself. It's a subclass of Module, which is also an instance of class, and Module is a subclass of Object, which is also an instance of Class. It is indeed quite circular — but this is part of the core language, not something in a library. The Ruby runtime itself doesn't have the same limits thast you or I do when we're writing Ruby code.
I've never heard the word "metaclass" used to talk about Class, though. It isn't used much in Ruby at all, but when it is, it's usually a synonym for what's officially called a "singleton class of an object," which is an even more confusing topic than Object-Module-Class triangle.