Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can someone explain the Class.superclass.class.superclass paradox?

It's probably not a paradox at all, but from a newbies perspective, it sure seems that way.

> Class.superclass => Module > Class.superclass.class => Class > Class.superclass.class.superclass => Module 

So a class's parent is module, but module is a class?

How can I make sense of this?

like image 560
Nathan Avatar asked May 11 '12 20:05

Nathan


2 Answers

TL;DR: Module is the superclass of Class. Module is an instance of Class.


Let me try to explain it more clearly. Please forgive my handwritten drawings - I don't have any fancy drawing software.

Every class in Ruby has 1 superclass*.

enter image description here

*Except for BasicObject, which doesn't have a superclass.

Read the above graphic like this: The superclass of Float is Numeric. The superclass of Numeric is Object, etc...

When you instantiate an object, the object will be an instance of some class. For example, "Nathan" is an instance of the String class. So is "Joe" or "John". 1 is an instance of the Fixnum class, as are 2, 3, 4, etc...

enter image description here

Read the above graphic like this: "Joe" is an instance of String. 1 is an instance of Fixnum, etc...

Well, in Ruby, unlike in most other languages, Class is a just another class, and it can be instantiated, too, just like Fixnum or String.

enter image description here

Read the above graphic like this: 0.01 is an instance of Float. String is an instance of Class, etc...

Realize that Fixnum is an instance of Class, just like "Nathan" is an instance of String. Just like "John" is an instance of String, Float is just an instance of Class. Every class is just an an instance of Class, even Class itself!

Whenever you write a new class in your app, you are just instantiating a new object whose class is Class, just like Hash.new instantiates a new Hash, or "Nathan" instantiates a new String.

# By running this, you will be instantiating a new Class, and  # it will be named Post  class Post < ActiveRecord::Base end  # Here is another perfectly valid way to write the above code: Post = Class.new(ActiveRecord::Base)  # you can even instantiate a Class without giving it an explicit name: x = Class.new(ActiveRecord::Base)  # and since your new things are classes, they can be instantiated obj1 = Post.new obj2 = x.new 

Furthermore, Module is just another instance of Class. Whenever you write a new module in your app, you are just instantiating a new Module.

# this will instantiate a new Module, and assign it to Foo module Foo end  # Here is another perfectly valid way to write the above code: Foo = Module.new  # you can even instantiate a Module without giving it an explicit name. m = Module.new 

An aside: A Module is just a collection of methods and constants. Classes are also a collection of methods and constants, but with the added functionality of being able to be instantiated. A module cannot be instantiated. That is, m.new will not work.

So, referring back to the top graphic, your question can be answered directly:

So a class's parent is module, but module is a class?

You can see from the top graphic: Module is the superclass of Class.

From the bottom graphic: Module is an instance of Class.

like image 168
John Douthat Avatar answered Sep 20 '22 11:09

John Douthat


  • Class extends Module. This is demonstrated in your 1st and 3rd examples.
  • Module extends Object.
  • Object extends BasicObject
  • BasicObject is the root of the class hierarchy

In your second example Class.superclass.class, you're calling Module.class. Module refers to a class, the Module class.

AnyClass.superclass.class will return Class, except for BasicObject.superclass.class

The distinction between a class and an instance is important. BasicObject is a class. It is a class that extends nil, which is a fancy way of saying it has no superclass. It is the root of the tree. EVERYTHING is an object, which is another way of saying everything is an instance of some class.

String Example

"Nathan" is an object. "Nathan" is an instance of the String class. "Nathan" is not a class. "Nathan" has no superclass, because "Nathan" is not a class.  String is an object. String is an instance of the Class class. String's superclass is Object.  Object is an object. Object is an instance of the Class class. Object's superclass is BasicObject.  BasicObject is an object. BasicObject is an instance of the Class class BasicObject's superclass is nil.  nil is an object. nil is an instance of the NilClass class nil has no superclass, because it is not a class. 

Fixnum example

1 is an object. 1 is an instance of the Fixnum class. 1 is not a class. 1 has no superclass, because it is not a class.  Fixnum is an object. Fixnum is an instance of the Class class. Fixnum's superclass is Integer.  Integer is an object. Integer is an instance of the Class class Integer's superclass is Numeric.  Numeric is an object. Numeric is an instance of the Class class. Numeric's superclass is Object.  # everything below here is in the above example. Object is an object. Object is an instance of the Class class. Object's superclass is BasicObject.  BasicObject is an object. BasicObject is an instance of the Class class BasicObject's superclass is nil.  nil is an object. nil is an instance of the NilClass class nil has no superclass, because it is not a class. 

So, finally:

Class is an object. Class is an instance of the Class class. # this is probably the most important part. Class's superclass is Module # 2nd most important part  Module is an object Module is an instance of the Class class. # 3rd Module's superclass is Object # 4th  # everything below here is in the above examples. Object is an object. Object is an instance of the Class class. Object's superclass is BasicObject.  BasicObject is an object. BasicObject is an instance of the Class class BasicObject's superclass is nil.  nil is an object. nil is an instance of the NilClass class nil has no superclass, because it is not a class. 

In table form:

enter image description here

And if you would like to verify that it's all true, you can just run it in Ruby

"Nathan".is_a?(BasicObject) # => true    "Nathan" is an object. "Nathan".class #=> String                "Nathan" is an instance of the String class. "Nathan".is_a?(Class) #=> false          "Nathan" is not a class. "Nathan".superclass # NoMethodError      "Nathan" has no superclass, because "Nathan" is not a class.  String.is_a?(BasicObject) #=> true       String is an object. String.class #=> Class                   String is an instance of the Class class. String.superclass #=> Object             String's superclass is Object.  Object.is_a?(BasicObject) #=> true       Object is an object. Object.class #=> Class                   Object is an instance of the Class class. Object.superclass #=> BasicObject        Object's superclass is BasicObject.  BasicObject.is_a?(BasicObject) #=> true  BasicObject is an object. BasicObject.class #=> Class              BasicObject is an instance of the Class class BasicObject.superclass #=> nil           BasicObject's superclass is nil.  nil.is_a?(BasicObject) #=> true          nil is an object. nil.class #=> NilClass                   nil is an instance of the NilClass class nil.superclass # NoMethodError           nil has no superclass, because it is not a class. 

And starting from Class:

Class.is_a?(BasicObject) #=> true        Class is an object. Class.class #=> Class                    Class is an instance of the Class class. # this is probably the most important part. Class.superclass #=> Module              Class's superclass is Module # 2nd most important part  Module.is_a?(BasicObject) #=> true       Module is an object Module.class #=> Class                   Module is an instance of the Class class. # 3rd Module.superclass #=> Object             Module's superclass is Object # 4th  Object.is_a?(BasicObject) #=> true       Object is an object. Object.class #=> Class                   Object is an instance of the Class class. Object.superclass #=> BasicObject        Object's superclass is BasicObject.  BasicObject.is_a?(BasicObject) #=> true  BasicObject is an object. BasicObject.class #=> Class              BasicObject is an instance of the Class class BasicObject.superclass #=> nil           BasicObject's superclass is nil.  nil.is_a?(BasicObject) #=> true          nil is an object. nil.class #=> NilClass                   nil is an instance of the NilClass class nil.superclass # NoMethodError           nil has no superclass, because it is not a class. 
like image 22
11 revs Avatar answered Sep 22 '22 11:09

11 revs