Ruby craziness: Class vs Object?
Basically the key thing to understand is that every class is an instance of the Class
class and every class is a subclass of Object
(in 1.8 - in 1.9 every class is a subclass of BasicObject
). So every class is an object in the sense that it is an instance of a subclass of Object
, i.e. Class
.
Of course this means that Class
is an instance of itself. If that makes your brain hurt, just don't think about it too deeply.
Object
and Class
are is_a? Object
x.is_a? y
returns true
if x.class == y or x.class < y
, i.e. if x
's class is y
or x
's class inherits from y
. Since every class inherits from object x.is_a? Object
returns true no matter what x
is. (In 1.8 anyway, in 1.9 there's also BasicObject
which is now the most basic class in the inheritance hierarchy).
They are also is_a? Class
Both Object
and Class
are indeed classes, so that should not be surprising.
They are also instance_of? Class
, but not instance_of? Object
.
Unlike is_a?
, x.instance_of? y
only returns true if x.class == y
, not if x.class
is a subclass of y
. So since both x
and y
are instance_of? Class
, they're not instance_of? Object
.
right, nothing can be instance of object.
That's not true. Object.new.instance_of? Object
is true.
kind_of?
kind_of?
is an alias for is_a?
, so see above.
So both are exactly same, then why do we have both these.?
It should be pointed out that everything up to now is true for all classes. E.g. String.is_a? Object
, String.is_a? Class
and String.instance_of? Class
are true and String.instance_of? Object
is false for the same reasons as above. (Also String.is_a? String
and String.instance_of? String
are both false for the same reasons - String is a class, not a string).
You can not conclude from this that all the classes are the same. They're just all instances of the same class.
Comparing methods
Since both Object
and Class
are classes, they both have all the instance methods defined by Class
. Class
additionally has the singleton method nesting
. nesting
tells you which module you're currently nested in, it has nothing to do with inheritance.
For any given class TheClass.methods
will return the instance methods defined by Class
(e.g. superclass
, which returns the class which TheClass
inherits from, and new
which creates a new instance of TheClass
) plus the singleton methods defined by that class.
Anyway methods
only tells you which methods can be called directly on a given object. It does not tell you which methods can be called on an instance of a class. For that you can use instance_methods
, which returns significantly different results for Object
and Class
.
Ruby's Classes and Objects
You have several things wrong.
- (2.) The reason
Class
,Module
,Object
, andBasic Object
are instances ofClass
is not becauseClass < Module < Object < BasicObject
. It has nothing to do with it. - (3.)
(Object.new).instance_of? Class
returnsfalse
not becauseObject.new
is an instance ofObject
. It is because it is not an instance ofClass
. Class.is_a? Object
istrue
not because [the mentioned]Class
is a subclass ofObject
. It is because (the mentioned)Class
is an instance ofClass
(which is not mentioned), which is a subclass ofObject
.
The answer to the question is: Object.is_a? Class
returns true
because Object
is an instance of Class
.
If you want to know the class of an instance, use instance_of?
or class
methods.
3.is_a?(Object) # => false
3.is_a?(Fixnum) # => true
3.class # => Fixnum
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 class and object - different methods of comparison
You are right ==
and ===
are different methods on the String class and an instance of String. Have a look at the different documentation for
Module.==
Module.===
String#==
String#===
Why String == String
evaluates to true
but String === String
does not?
As you can see in the docs Module.==
basically means if both sides are the same Object. Is the String
class the same as the String
class? Yes. But Module.===
returns true
if the right side is an instance of the class on the left. Id String
an instance of String
? No.
Why s1 === String
is false
but String === s1
is true
?
s1 === String
calls ===
on an instance of string. This method returns true
when both sides are the same object. Are an instance of String
and the class Sting
the same object? No. But String === s1
has – as already explained before the meaning of is_a?
: Is an instance of String
an instance of String
? Yes.
Why do methods inside a class become instance methods instead of becoming singleton methods of the class itself?
It works similarly to message sends and constant lookup:
- The general format of a message send is
foo.bar
, which sends the messagebar
tofoo
. If you leave outfoo
, the message will be sent to the default receiver (which isself
). - The general format of a constant lookup is
Foo::Bar
, which looks up the constantBar
in the moduleFoo
. If you leave outFoo
, the constant will be looked up in the default constant context (or cref). The general format of a method definition is
def foo.bar
, which defines the methodbar
in the singleton class offoo
. If you leave outfoo
, the method will be defined in the default definition context (or default definee):- At the top-level, the default definee is
Object
. (Also, the methods becomeprivate
.) - Within a module declaration body, the default definee is
self
(and notself
's singleton class, like you assumed!) - Within a method body, the default definee is the syntactically enclosing module. (Put another way:
def
doesn't change the default definee.) instance_eval
changes the default definee to the receiver's singleton classclass_eval
changes the default definee to the receiver
- At the top-level, the default definee is
Related Topics
Why Is _File_ Uppercase and _Dir_ Lowercase
Strange Inability to Require Config/Boot After Upgrading to Ruby 1.9.2
Flattening Nested Hash to a Single Hash with Ruby/Rails
How to Install the Ruby Ri Documentation
How to Install Jekyll on Osx 10.11
Escaping Single and Double Quotes in a String in Ruby
Why Did Matz Choose to Make Strings Mutable by Default in Ruby
Differencebetween Using .Exists, and .Present? in Ruby
Why Should One Use a Http Server in Front of a Framework Web Server
How to Check to See If My Array Includes an Object
How to Validate Exits and Aborts in Rspec
Using a String as a Variable at Run Time
Iterate Over a Deeply Nested Level of Hashes in Ruby
How to Detect Certain Unicode Characters in a String in Ruby