What's the difference between Object and BasicObject in Ruby?
BasicObject was introduced in Ruby 1.9 and it is a parent of Object (thus BasicObject
is the parent class of all classes in Ruby).
BasicObject
has almost no methods on itself:
::new
#!
#!=
#==
#__id__
#__send__
#equal?
#instance_eval
#instance_exec
BasicObject can be used for creating object hierarchies independent of
Ruby's object hierarchy, proxy objects like the Delegator class, or
other uses where namespace pollution from Ruby's methods and classes
must be avoided.BasicObject does not include Kernel (for methods like puts) and
BasicObject is outside of the namespace of the standard library so
common classes will not be found without a using a full class path.
Object mixes in the Kernel module, making the built-in kernel
functions globally accessible. Although the instance methods of Object
are defined by the Kernel module...
You can use BasicObject
as a parent of your object in case if you don't need methods of Object
and you would undefine them otherwise:
# when you inherit Object
class Tracer
instance_methods.each do |m|
next if [:__id__, :__send__].include? m
undef_method m
end
# some logic
end
# when you inherit BasicObject
class Tracer < BasicObject
# some logic
end
Ruby: is_a? and instance_of? in BasicObject
You can steal is_a?
from Kernel
:
class My < BasicObject
define_method(:is_a?, ::Kernel.method(:is_a?))
end
m = My.new
m.is_a?(My) #=> true
m.is_a?(BasicObject) #=> true
m.is_a?(Object) #=> false
If you're going to build your own object hierarchy, you could also define your own Kernel
, something like:
module MyKernel
[:is_a?, :instance_of?, :class].each do |m|
define_method(m, ::Kernel.method(m))
end
end
class My < BasicObject
include ::MyKernel
end
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
.
What is the difference between type of a class and superclass of a class in ruby?
Its a bit tricky. In Ruby everything is an Object (depending on your version).
- Nil has its own NilClass, as it does not allow NilClass.new, which Object and Class allow. It is an object so you can call methods on it like nil.nil? etc.
- Object is the highest Class, everything inherits from Object, even NilClass
- Class is also an Object, it knows how to instantiate Objects from itself with the new method.
It is really weird at first, but I found the explanation from Dave Thomas quite revealing.
See: http://www.infoq.com/presentations/metaprogramming-ruby and http://pragprog.com/screencasts/v-dtrubyom/the-ruby-object-model-and-metaprogramming. The later is commercial.
How the BasicObject, Object, and Kernel interact each other?
You are confusing two meanings of "is": "instance of" and "subclass of".
1) Regarding subclass relation:
Class
is a subclass ofModule
.Module
is a subclass ofObject
.Object
is a subclass ofBasicObject
.
And due to transitivity, Class
is a subclass of Object
and of BasicObject
, and Module
is a subclass of BasicObject
. But there is no circularity here. For example, BasicObject
is not a subclass of Class
, Module
, or Object
.
2) Regarding instantiation relation:
Class
is an instance ofClass
(as well as (kind) ofModule
,Object
,BasicObject
).Module
is an instance ofClass
(as well as (kind) ofModule
,Object
,BasicObject
).Object
is an instance ofClass
(as well as (kind) ofModule
,Object
,BasicObject
).BasicObject
is an instance ofClass
(as well as (kind) ofModule
,Object
,BasicObject
).
But there is no circularity in instantiation relation. Circularity is a notion defined on transitive relations. For example, If A → B
and B → C
, then it follows that A → C
due to transitivity, and if it is C → A
as well, then there is circularity. But instantiation relation is not transitive. "A is an instance of B" and "B is an instance of C" does not mean that "A is an instance of C". So circularity cannot be defined on instantiation relation in a non-trivial way.
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
IRB and Ruby Object Model
On Ruby classes al also objects, that's why the class of a class is actually Class
.
That explains why:
Class.class #=> Class
MyClass.class #=> Class
Class.class == MyClass.class #=> true
You are not calling class
over an instance of each class but calling it over the classes itself. Is almost the same as:
"hey".class #=> String
"jude".class #=> String
"hey".class == "jude".class #=> true
Here is what you were probably expecting at the beginning:
MyClass.new.class #=> MyClass
Class.new.class #=> Class
MyClass.new.class == Class.new.class #=> false
Related Topics
Rails: Unpermitted Parameter in Rails 5
How to Url Encode a String in Ruby
How to Preserve Request Url With Nginx Proxy_Pass
Spinning Background Tasks in Rails
Rails: How to Use Dependent: :Destroy in Rails
Ruby on Rails: Can You Put Ruby Code in a Yaml Config File
Ruby Read CSV File as Utf-8 And/Or Convert Ascii-8Bit Encoding to Utf-8
Rails 3 - No Such File to Load -- Openssl
Best Way to Highlight Current Page in Rails 3? - Apply a CSS Class to Links Conditionally
Gem.Source_Index Is Deprecated, Use Specification. Should I Re-Install Gem or Rails
What's the Difference Between Gets.Chomp() VS. Stdin.Gets.Chomp()
Finding Out Current Index in Each Loop (Ruby)
Get the Value of an Instance Variable Given Its Name
Rails: Postgres Permission Denied to Create Database on Rake Db:Create:All
Ruby Datetime Parsing from 'Mm/Dd/Yyyy' Format
Why Do This Ruby Object Have Both To_S and Inspect Methods That Appear to Do the Same Thing