Ruby craziness: Class vs Object?

2019-01-29 17:58发布

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, ??

7条回答
Fickle 薄情
2楼-- · 2019-01-29 18:30

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.

查看更多
我只想做你的唯一
3楼-- · 2019-01-29 18:31

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

查看更多
倾城 Initia
4楼-- · 2019-01-29 18:36

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 
查看更多
霸刀☆藐视天下
5楼-- · 2019-01-29 18:36

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.parent  
=> 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.

查看更多
等我变得足够好
6楼-- · 2019-01-29 18:38

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.

查看更多
乱世女痞
7楼-- · 2019-01-29 18:38

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.

查看更多
登录 后发表回答