Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is EVERYTHING an instance of Class in Ruby? [duplicate]

Tags:

ruby

I don't quite get some things about the Ruby object model. First, is EVERYTHING in Ruby an instance of Class? These all produce true:

p Object.instance_of?(Class)
p Class.instance_of?(Class)
p Module.instance_of?(Class)
p BasicObject.instance_of?(Class)
class Hello; end
p Hello.instance_of?(Class)

I can't quite get how is it possible, if Object is a superclass of Class, how can it be both a superclass of Class and an instance of it at the same time (most diagrams on the Ruby Object Model clearly state this hierarchy)? Which allows for some crazyness like this:

p BasicObject.is_a?(Object) #=> true

where BasicObject.class is Class, and Class.is_a?(Object).

By the way, using Ruby 2.0.

like image 345
daremkd Avatar asked Dec 25 '14 15:12

daremkd


2 Answers

First, is EVERYTHING in Ruby an instance of Class?

No, not everything is an instance of Class. Only classes are instances of Class.

There are lots of things which aren't instances of Class: strings, for example, are instances of String, not Class. Arrays are instances of Array, integers are instances of Integer, floats are instances of Float, true is an instance of TrueClass, false is an instance of FalseClass, nil is an instance of NilClass, and so on.

Every class is an instance of Class, just like every string is an instance of String.

if Object is a superclass of Class, how can it be both a superclass of Class and an instance of it at the same time (most diagrams on the Ruby Object Model clearly state this hierarchy)?

Magic.

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 always Object. [Note: there may be implementation-defined superclasses of Object, but eventually, there will be one which doesn't have a superclass.]
  • Object is an instance of Class, which is a subclass of Object (which means that indirectly Object is an instance of Object itself)
  • Class is a subclass of Module, which is an instance of Class
  • Class is an instance of Class

None of these things can be explained in Ruby.

BasicObject, Object, Module and Class 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 its superclass pointer and its class pointer to null.

Then, it creates Object, setting its superclass pointer to BasicObject and its class pointer to null.

Next, it creates Module, setting its superclass pointer to Object and its class pointer to null.

Lastly, it creates Class, setting its superclass pointer to Module and its class pointer to null.

Now, we can overwrite BasicObject's, Object's, Module's, and Class's class pointer to point to Class, and we're done.

This is easy to do from outside the system, it just looks weird from the inside.

like image 70
Jörg W Mittag Avatar answered Oct 20 '22 08:10

Jörg W Mittag


You should notice that:

p BasicObject.instance_of?(BasicObject) 

prints false.

That is, the expression BasicObject is not an instance of BasicObject, it is an instance of something else, that is, it is a Class object, which represents an object that holds (for example) the class methods, such as new.

For example:

p (BasicObject.new()).instance_of?(BasicObject)

prints true, and

p (BasicObject.new()).instance_of?(Class)

prints false.

like image 24
Jean Hominal Avatar answered Oct 20 '22 10:10

Jean Hominal