Can someone explain the Class.superclass.class.superclass paradox?
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*.
*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...
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.
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.
The Class/Object Paradox confusion
You can see the problem in this diagram:
(source: phrogz.net)
All object instances inherit from Object
. All classes are objects, and Class
is a class, therefore Class
is an object. However, object instances inherit from their class, and Object
is an instance of the Class
class, therefore Object
itself gets methods from Class
.
As you can see in the diagram, however, there isn't a circular lookup loop, because there are two different inheritance 'parts' to every class: the instance methods and the 'class' methods. In the end, the lookup path is sane.
N.B.: This diagram reflects Ruby 1.8, and thus does not include the core BasicObject
class introduced in Ruby 1.9.
Ruby metaclass confusion
how do this work
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
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.
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 named Class
, it is reopening the existing class Class
, 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:
class Class
def new(*args, &block)
obj = allocate # another magic thing that cannot be explained in Ruby
obj.initialize(*args, &block)
return obj
end
end
[Note: actually, initialize
is private, so you need to use obj.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.
What does this Ruby syntax mean: if self Class::Name?
It checks if self
is a subclass of Example::Class::Name
Check out the Module docs :)
Can someone help explain the post_initialize callback for class creation (Sandi Metz)
The important thing to understand here is that in this code:
def initialize(args = {})
# ...
post_initialize(args)
end
...post_initialize
has an implicit receiver, self
. In other words, post_initialize(args)
here is equivalent† to self.post_initialize(args)
, and self
is an instance of MountainBike. Method lookup always starts with the receiver's class,‡ so it has no trouble finding MountainBike#post_initialize
.
† That's a lie; it's not equivalent when it comes to privacy; private
methods cannot be called with an explicit receiver.
‡ That's also a lie; it actually starts with the receiver's singleton class, but then it tries its class.
Every class is implicitly a subclass of Object Java
Meaning of implicitly - suggested though not directly expressed.
If samething applied in Java classes. Consider there is a class called Test
.
If you write
public class Test {....}
That is equivalent to
public class Test extends Object {....}
Though you didn't write it, it's equivalent to it. You need not to write extends Object
manually. Internally JVM treats that your class is extends Object
. Since the part after extends is your class, here Object
is your super class.
But,
When you write
public class Test extends BigTest{....}
Things changed now. You are telling BigTest
is my parent class. That means you are implicitly writing yourself that BigTest
is my parent. Interesting part here is though BigTest is your direct Parent
class, internally Object
also your Parent
.
So now you have 2 parent classes. One is BigTest
which you mentioned and other is Object. If you didn't mention anything, only Object
is your Parent.
Edit :
This is the reason that you will see extra list of method when you will try to call any member of class with object-reference. Those methods are declared in Object class.
why java do this? any feature of this?
Yes. There are benefits of it. Main reason is to reduce the code duplication.
Continue reading here .... Why Object as super class in Java ?
Inheritance in java and Superclasses(Object, Class)
Everything is an Object, that said you could see the structure as this:
Object
Animal
Cat
and not as this:
Object Animal
Cat
Where Cat
extends both, it's not like this last example, but it's Cat
that extends
Animal
which extends
Object
.
Related Topics
How to Get the Current Time as 13-Digit Integer in Ruby
How Does Shovel (<<) Operator Work in Ruby Hashes
Why Does My Ruby 'Ri' Tool Not Return Results in Command Prompt
What Does 'Def Self.Function' Name Mean
Error: SASS Installation for Windows
How to Configure Ruby on Rails with Oracle
How to Count the Number of Records That Have a Unique Value in a Particular Field in Ror
How to Select Every Nth Item in an Array
Gem.Source_Index Is Deprecated, Use Specification. Should I Re-Install Gem or Rails
Get the Value of an Instance Variable Given Its Name
How to Make Instance Variables Private in Ruby
How to Print Out the Contents of an Object in Rails for Easy Debugging
Using Instance Variables in Class Methods - Ruby