Why instances don't have 'Class' as a parent in Ruby? - ruby

p 'a'.class.ancestors #=> [String, Comparable, Object, Kernel, BasicObject]
p String.class.ancestors #=> [Class, Module, Object, Kernel, BasicObject]
Suppose I call a method on 'a'. It first goes and looks for that object in the String class, if it doesn't find it there, it looks in Comparable etc.
Now if I call a method on the Class class, it first goes to 'Class', then 'Module' etc.
What I don't understand is this. Why, when I call a method on an instance of a string like 'a', it doesn't look-up the methods in 'Class'? Why doesn't 'a' have Class in its ancestors list?

Because 'a' is not a class, 'a' is a string, that's why 'a' is an instance of the class String. String is a class, so it's an instance of the class Class.
Keep this in mind, Class is not and ancestor of String. Class is the class of String.
When you call a method on 'a', ruby will try to find that method in 'a''s class String and its ancestors, none of which is Class
More Discussion
Normally speaking, when we are not having such abstract discussion, you'd say 'a' is a String, or String is a Class. But that might lead to confusion in the current context.
This is because the is a relationship in current context could mean at least two different thing. x is a Y could either mean that object x is an instance of class Y, or it could mean that class x inherits from class Y. (of course naming conventions would suggest that x is an object and Y is a class.. but those are not solid enough)
This vagueness of the is a relationship is the root of the confusion here. Because in ruby, all classes are also objects, objects of type Class. To make the whole situation both confusing and elegant at the same time, Class is also an object! ...of type Class!!
[7] pry(main)> 'a'.ancestors
NoMethodError: undefined method `ancestors' for "a":String
from (pry):7:in `__pry__'
[8] pry(main)> 'a'.class.ancestors
=> [String, Comparable, Object, PP::ObjectMixin, Kernel, BasicObject]
[9] pry(main)> String.ancestors
=> [String, Comparable, Object, PP::ObjectMixin, Kernel, BasicObject]
[10] pry(main)> String.class.ancestors
=> [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
[11] pry(main)> Class.ancestors
=> [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
[12] pry(main)> Class.class.ancestors
=> [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
So if we were to simply talk in terms of is a relationship. String is a Class and a String is a Comparable. But String doesn't inherit from Class, it's an instance of Class. And String is not an instance of Comparable, it inherits from Comparable.
Now is a good time to refresh the meaning of the inherits from relationship. String inherits from Comparable, that means that all objects of type String will also inherit behavior from class Comparable. And since String does not inherit from Class, object instances of type String won't inherit any behavior from class Class.
Back to "is a" relationship. String is an Object. Now this applies to both relationships. String certainly inherits from Object. But also Class, what String is an instance of, inherits from Object. And thus String also inherits the behavior of class object. So when we say String is an Object, it could mean either of the things. Although, if we were talking about inheritance, we'd probably say "a String is an Object", meaning that instances of class String are also objects. While saying "String is an Object" (notice I dropped the article 'a') we'd mean that the class String itself is an object.
I just realized something else. Remember how we declare static methods in Ruby? Ruby on rails - Static method
You say...
class X
def self.static_method
...
end
end
If you think about it, by using the keyword self, we are referring the object nature of X. So when later you call X.static_method, you are accessing X as an object and referring to an instance method associated with object X.
Hope I've not confused you guys too much.

Related

How does Object know about the const_get method?

I was reading another question with an answer that mentions using the Module#const_get instance method to find a class in a module. For example:
module M
class C
end
end
p M.const_get 'C'
#=> M::C
I was curious about the const_get method so I used ri and found:
ri Module#const_get
...
This method will recursively look up constant names if a namespaced
class name is provided. For example:
module Foo; class Bar; end end
Object.const_get 'Foo::Bar'
...
It seems like Object::const_get is a singleton method. Using it in our context works:
module M
class C
end
end
p Object.const_get 'M::C'
#=> M::C
But there's nothing documented about that singleton method:
ri Object::const_get
Nothing known about Object::const_get
ri Object.const_get
Nothing known about Object.const_get
This confused me because I know a Module is an Object but an Object is not a Module:
Module.ancestors
#=> [Module, Object, Kernel, BasicObject]
Object.ancestors
#=> [Object, Kernel, BasicObject]
Except then I used the Object#is_a? instance method to check and saw that I was wrong about that:
Module.is_a? Object
#=> true
Object.is_a? Module
#=> true
What started as an innocent ri query has led me to be confused about the entire Ruby object model.
Why does Object.is_a? Module #=> true if Module is not in Objects ancestor chain?
How does Object know about the const_get method?
This is an artifact of the ill-understood separation between an object's class and an object's singleton class, a sort of shadow class that each class uses for things like this.
You can access this easily in Ruby 2.5+ with the singleton_class method:
Object.singleton_class.ancestors
# => [#<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]
Where Module makes an appearance here, so that's how those methods get mixed in and are callable via Object.
Object itself has a comparatively dull inheritance chain:
Object.ancestors
#=> [Object, Kernel, BasicObject]
Every object in Ruby has a class, even Class is an Object, which also has an associated Class.
I think your confusion stems from looking at Object from two directions at once:
Object is a class so Object.ancestors can be used to look at the inheritance hierarchy. This tells you that Object < Kernel is true and Object < Module is false.
Classes in Ruby are also objects, specifically they're instances of the Class class. This tells you that Object.is_a? Class and Object.is_a? Module in the same way that 'pancakes'.is_a? String. And that Object.const_get is a method call in the same way that 'pancakes'.upcase is a method call.
You can think of some_obj.is_a? SomeClass as a shorter way of saying some_obj.class.ancestors.include? SomeClass.
Answering your specific questions:
Why does Object.is_a? Module #=> true if Module is not in Object's ancestor chain?
Because is_a? and ancestors are looking at different things.
How does Object know about the const_get method?
Because Object is an instance of the Class class and Class includes Module in its ancestors. Similarly to how 'pancakes' is an instance of the String class which has Kernel in its ancestors so 'pancakes' has an object_id method.
Object.is_a? Module #=> true
is_a? is asking whether Object is an instance (or specialised instance) of Module. Class is a subclass of Module so all instances of Class are really just specialised instances of Module. Since Object is an instance of Class, it follows that Object is also an instance of Module.
Module#const_get
const_get is an instance method defined within the Module class. Since Object is an instance of Module (for reasons discussed above), it has access to Module#const_get.

Ruby Object and Module

I'm confused about these two class when I was reading Module document.
First of all, I saw there is a way to set the named constant to the given object.
Object.const_set("FOO", 40)
But I check ruby doc, there is no const_set in Object method, then I found out it was defined in Module.
I thought Object is the default root of all Ruby objects. Why it can use module method? I am confused about the relationship between those.
As shown below :const_set is an instance method stored in Module:
Module.instance_methods(false).include? :const_set #=> true
Also note that Object is an instance of Class:
Object.instance_of? Class #=> true
And Class is a subclass of Module:
Class.superclass #=> Module
All of this means that instance methods defined within Module are available to Class objects via inheritance. So any instance of Class (such as Object) has at its disposal all the instance methods (including :const_set) stored in Module.
In ruby, basically every class is an instance of the Class class and every class is a subclass of Object. And both Object and Class are classes. If you do
Object.is_a?class
Class.is_a?class
In both cases, you will get a true value. Class has Module as one of the ancestor, therefore, you can use
Object.const_set("FOO", 40)
There is also #ancestors to give you some more context on the object model.
> Module.ancestors
=> [Module, Object, PP::ObjectMixin, Kernel, BasicObject]

How to find any methods ancestor chain?

class Taco
# . . .
end
Get ancestor chain:
Taco.ancestors
#=> [Taco, Object, Kernel, BasicObject]
Say I want to find the "parent" class and it's ancestor chain for a ruby defined method. How would I go about doing that?
E.g. method_missing.parent.ancestors
And if everything is supposed to inherit from BasicObject why doesn't Kernel?
Object.ancestors
#=> [Object, Kernel, BasicObject]
Kernel.ancestors
#=> [Kernel]
BasicObject.ancestors
#=> [BasicObject]
Also Class inherits from Class and Module but why does my Taco class ancestor's chain not inherit from them and instead inherits directly from Object forward?
Class.ancestors
#=> [Class, Module, Object, Kernel, BasicObject]
You are looking for owner.
method(:puts).owner
#=> Kernel
method(:puts).owner.ancestors
#=> [Kernel]
Back to your taco example:
class Taco
def self.eat
"YUM"
end
end
Taco.method(:eat).owner
#=> #<Class:Taco>
Taco.method(:eat).owner.ancestors
#=> [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
Kernel is an instance of module. Check this out:
Kernel.class.ancestors
#=> [Module, Object, PP::ObjectMixin, Kernel, BasicObject]
Here is some further reading on the ruby object model if you're interested. Also, here's an image stolen from google images that may help solidify those concepts.
Specifically regarding your question: "Also Class inherits from Class and Module but why does my Taco class ancestor's chain not inherit from them and instead inherits directly from Object forward?"
Taco is an instance of Class, but its superclass is Object. An instance relationship and a superclass relationship are 2 completely different things.
For example: imagine you create a class Animal with a subclass Dog. Animal.new will give you an object which is an instance of Animal. The Dog class is not an instance of Animal (it is not itself an animal -- rather, it defines a type of animal). Its superclass is Animal.
Every object is an instance of some class -- call class to find out which one. But not all objects have a superclass -- only instances of Class do.
Additionally, Class does not inherit from Class. That is impossible. All classes appear at the beginning of their own ancestors, but that doesn't mean they inherit from themselves. That is just how the ancestors method works.

Ruby Object Model - ancestors of a class

I'm studying the Ruby Object Model from the book "Metaprogramming Ruby" and I understand the notion of how classes are Objects as well.
class A
end
A.ancestors # => [A, Object, Kernel, BasicObject]
A.class.ancestors # => [Class, Module, Object, Kernel, BasicObject]
What I'm confused about is that when I initially tried A.ancestors in irb, I expected the results that I got in A.class.ancestors - my thought process was: since A is a class, and a class is an instance of class Class, it's ancestor is Class. But Class doesn't seem to be an ancestor of A.
Would someone be able to clear up my confusion here?
The class A is an instance of Class, and you can see that via A.class
The class of an instance of A is A, and you access that via a = A.new; a.class
The method ancestors is showing the class hierarchy that an object of that class has (or would have) as its inheritance.
There are two parallel class hierarchy models going on in your example, and they only impinge on each other because Ruby represents its classes as objects for you to inspect and modify.
There is no fundamental reason to need A.class.ancestors and A.ancestors to intersect at all - except Ruby also has a deep class model with simple roots, so in practice that is what you'll see.
In fact I couldn't find any counter-example, even nil does this:
NilClass.ancestors
=> [NilClass, Object, Kernel, BasicObject]
NilClass.class.ancestors
=> [Class, Module, Object, Kernel, BasicObject]
This one is more enlightening though:
BasicObject.ancestors
=> [BasicObject]
BasicObject.class.ancestors
=> [Class, Module, Object, Kernel, BasicObject]

Ruby craziness: Class vs Object?

I just started playing with JRuby. This is my first ruby post. I had a hard time understanding classes vs objects in Ruby. It doesnt mean like what classes & objects in other Object oriented laguages. for an example
Class.is_a? Object
returns true
and
Object.is_a? Object
too.
so class & Object are both objects
here comes another one
Class.is_a? Class
returns true
and
Object.is_a? Class
too.
wait, i am not done yet
Object.instance_of? Class
Class.instance_of? Class
Both are true
Object.instance_of? Object
Class.instance_of? Object
Both are false. right, nothing can be instance of object.
And
Class.kind_of? Class
Object.kind_of? Class
both are true
Class.kind_of? Object
Object.kind_of? Object
both are true
So both are exactly same, then why do we have both these.?
After some more digging, i wrote this simple method to return method list supported by both
irb(main):054:0> def print_methods(obj)
irb(main):055:1> obj.methods.each do |mm|
irb(main):056:2* puts mm
irb(main):057:2> end
irb(main):058:1> end
Only method difference between print_methods(Object) and print_methods(Class) is
Nesting
if Nesting means inheritance, Is Object similar to the sealed class??
Can someone clarify me what is all this?
Update: To Edds comment
Interestingly i see lot of differences in the method list in
c=Class.new
print_methods(c)
&
o=Object.new
print_methods(o)
Now I understand Instance of a class is really an class instance (And this class instance is actually a Object) not an object instance. And even this instance allow me to span another instances
xx = c.new //works - c is an Object / and xx is a instance of an Object c
yy = o.new //nope - o is already a instance of an Object, so it cannot be instantiated again
So Finally, Object is really an instance of a Class. Because
xx.is_a? Class
is false, but
xx.is_a? Object
returns true
Am i right, ??
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.
In Ruby, everything is an Object including classes and modules. Object is the most low-level class (well, in Ruby 1.9.2 there is also BasicObject but this is an other story).
See the following output.
> Object.ancestors
# => [Object, Kernel, BasicObject]
> Class.ancestors
# => [Class, Module, Object, Kernel, BasicObject]
> Module.ancestors
# => [Module, Object, Kernel, BasicObject]
> String.ancestors
# => [String, Comparable, Object, Kernel, BasicObject]
As you can see, both Class and Module inherits from Object.
Back to your original assertions, you have to understand the difference bewteen
is_a?
kind_of'
instance_of?
They are not interchangeable. is_a? and kind_of? returns true if other is the same class or an ancestor. Conversely, instance_of? returns true only if other is the same class.
> Class.is_a? Object
# => true
> Class.kind_of? Object
# => true
> Class.instance_of? Object
# => false
One of the answers mentions this:
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.
So every class is an object in the sense that it is an instance of a
subclass of Object, i.e. Class.
I just want to word it differently for those who have a little brain twist. First ask yourself: What is an instance in programming? And what is a subclass in programming? An instance is just a realized variation of a blueprint (the Class). A subclass is simply a class (blueprint) that inherits from another class (blueprint). So when you create a new class:
class Apple
end
Apple is an instance of Class, that is, it is a realized variation of the blueprint. It takes the blueprint and fills in the details (methods and variables) with its own variation. Well, the blueprint inherits from another blueprint, which is Object. So every class is an instance of Class, which is a subclass of Object.
class A
end
A.superclass
=> Object
A.class
=> Class
Note Class has Module in its inheritance chain (Module included in Class as a mixin perhaps since Class's parent is Object?).
A.is_a?(Module)
=> true
Instances (A.new) of class A will have their own realized variations of A. But they are object instances. So we must distinguish class instances (e.g. class A end) and object instances ( a = A.new). Object instances have a different inheritance chain. They are a realized variation of a class instance blueprint, not a variation of class Class.
This means in their inheritance chain is not Class or Module. But rather other object instances, so if A has object instances and B has object instances and A inherits from B, when we instantiate a new object instance of A, this instance will have B instances in its inheritance chain.
They will also inherit from Object, since everything in Ruby inherits from Object.
a = A.new
=> #<A:0x007f966449b8d8>
a.is_a?(Class)
=> false
a.is_a?(Module)
=> false
a.is_a?(Object)
=> true
And this is the best way to think about it all. Do not go too deep with your thinking. Accept this as I have written it.
Ramesh, in ruby everything is an object, and a Class is no exception.
try this in irb
ruby-1.9.2-p136 :001 > o = Object.new
=> #<Object:0x000001020114b0>
ruby-1.9.2-p136 :002 > o.is_a? Class
=> false
ruby-1.9.2-p136 :003 > o.is_a? Object
=> true
in this case, I've created an instance of an Object, and checked if it's a class (false) or a Object (true).
A Class in ruby, is some kind of template object used to create instances of that class. Sorry that this is not super clear. The key concept is that ruby is a pure object oriented language, as opposed to Java.
The class/metaclass hierarchy is always a little puzzling :) Just for comparison, here's the one in Smalltalk; in Ruby, the setup is based on the same principles, except it doesn't have the Behavior and ClassDescription distinctions, and there are modules and eigenclasses to take into account.
A full explanation of the Smalltalk object model is available in Pharo by Example, as pointed by this related question.
As _why writes in this article
objects do not store methods, only classes can.
The first couple sections have some good points about classes vs objects
Think of Classes as global objects.

Resources