Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<blockquote> <p>how do this work</p> </blockquote> <p>Easy: it doesn't. Not in Ruby, anyway.</p> <p>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.</p> <p>In Ruby, some of those magic things are:</p> <ul> <li><code>Object</code> doesn't have a superclass, but you cannot define a class with no superclass, the implicit direct superclass is always <code>Object</code>. [Note: there may be implementation-defined superclasses of <code>Object</code>, but eventually, there will be one which doesn't have a superclass.]</li> <li><code>Object</code> is an instance of <code>Class</code>, which is a subclass of <code>Object</code> (which means that indirectly <code>Object</code> is an instance of <code>Object</code> itself)</li> <li><code>Class</code> is a subclass of <code>Module</code>, which is an instance of <code>Class</code></li> <li><code>Class</code> is an instance of <code>Class</code></li> </ul> <p>None of these things can be explained in Ruby.</p> <p><code>BasicObject</code>, <code>Object</code>, <code>Module</code> and <code>Class</code> all need to spring into existence at the same time because they have circular dependencies.</p> <p>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.</p> <p>For example, the Ruby implementation could first create <code>BasicObject</code>, setting both its <code>superclass</code> pointer and its <code>class</code> pointer to <code>null</code>.</p> <p>Then, it creates <code>Object</code>, setting its <code>superclass</code> pointer to <code>BasicObject</code> and its <code>class</code> pointer to <code>null</code>.</p> <p>Next, it creates <code>Module</code>, setting its <code>superclass</code> pointer to <code>Object</code> and its <code>class</code> pointer to <code>null</code>.</p> <p>Lastly, it creates <code>Class</code>, setting its <code>superclass</code> pointer to <code>Module</code> and its <code>class</code> pointer to <code>null</code>.</p> <p>Now, we can overwrite <code>BasicObject</code>'s, <code>Object</code>'s, <code>Module</code>'s, and <code>Class</code>'s <code>class</code> pointer to point to <code>Class</code>, and we're done.</p> <p>This is easy to do from outside the system, it just looks weird from the inside.</p> <p>Once they <em>do</em> 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.</p> <p>In your example, the <code>class Class</code> is not creating a new class named <code>Class</code>, it is reopening the <em>existing</em> class <code>Class</code>, which was given to us by the runtime environment.</p> <p>So, it is perfectly possible to explain the default behavior of <code>Class#new</code> in plain Ruby:</p> <pre><code>class Class def new(*args, &amp;block) obj = allocate # another magic thing that cannot be explained in Ruby obj.initialize(*args, &amp;block) return obj end end </code></pre> <p>[Note: actually, <code>initialize</code> is private, so you need to use <code>obj.send(:initialize, *args, &amp;block)</code> to circumvent the access restriction.]</p> <p>BTW: <code>Class#allocate</code> 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, <code>Class#allocate</code> is something that has to be provided by the runtime system as well.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload