What's the Difference Between Object and Basicobject in Ruby

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 of Module.
  • Module is a subclass of Object.
  • Object is a subclass of BasicObject.

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 of Class (as well as (kind) of Module, Object, BasicObject).
  • Module is an instance of Class (as well as (kind) of Module, Object, BasicObject).
  • Object is an instance of Class (as well as (kind) of Module, Object, BasicObject).
  • BasicObject is an instance of Class (as well as (kind) of Module, 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, and Basic Object are instances of Class is not because Class < Module < Object < BasicObject. It has nothing to do with it.
  • (3.) (Object.new).instance_of? Class returns false not because Object.new is an instance of Object. It is because it is not an instance of Class.
  • Class.is_a? Object is true not because [the mentioned] Class is a subclass of Object. It is because (the mentioned) Class is an instance of Class (which is not mentioned), which is a subclass of Object.

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



Leave a reply



Submit