I've just got deeper in Ruby hierarchy to understand it. For example,
class Test
end
t = Test.new
So, if I want to get class of t I need to get 'class' property:
t.class # 'Test'
If I want to get parent of Test class I should use 'superclass' method:
t.class.superclass # BasicObject
But also Test is an instance of Class class. So, if I execute the following thing:
t.class.class # Class
So, I don't understand the difference between 'superclass' and 'class.class'; why aren't Class superclass for Test? What does it mean? Doest Test inherit methods of Class or BasicObject or both ones? Please, explain this thigns to me. I came from Java and I didn't hear about this features before. Thanks.
First of all, by default, implicit superclass of the class you define is Object, not BasicObject.
Now, Test.superclass methods returns class that Test directly inherits from. While Test.class returns class that Test is instance of. Remember that classes in Ruby are also objects, all objects in Ruby belongs to some class.
Every object responds to class. It says what class the object is an instance of.
Only classes respond to superclass. It says what class the class is a subclass of.
Foo = Class.new # class Foo; end
foo = Foo.new
Foo.class # Class
foo.class # Foo
Bar = Class.new(Foo) # class Bar < Foo; end
Bar.class # Class
Bar.superclass # Foo
All classes are instances of Class. Ruby does not allow subclasses of Class.
All objects are descendents of class Object. Class is object too and it is an instance of Object, which can seem a little weird.
class Test
end
Test.class # => Class
Test.superclass # => Object
Object.class # => Class
Class.superclass # => Module
Module.class # => Class
Module.superclass # => Object
Object.superclass # => BasicObject
All descendents of class Object inherit quite a lot of methods like clone, dup, freeze and many many other methods. On the other hand BasicObject will provide you almost no methods - it doesn't even provide you methods: methods and public_methods.
Related
By definition, a singleton class of an object also inherits the singleton class of the superclass of the object. The BasicObject in ruby doesn't have any superclass as it is the most basic level class
>> BasicObject.superclass
=> nil
But when the same method called on its singleton class, it results:
>> BasicObject.singleton_class.superclass
=> Class
and also why no other object in ruby have the Class class as its superclass?
How the logic behind the superclass of singleton_class of BasicObject is implemented in Ruby?
In general, the superclass of the singleton class of an object is the class of the object. I.e. for any object foo with a singleton class, the following holds:
foo.singleton_class.superclass == foo.class
However, for classes, this would be somewhat boring: the class of every class is Class, so the superclass of every class's singleton class would always be Class.
That is not particularly useful, since it would break some reasonable assumptions. For example, if I have something like this:
class Super
def self.super_singleton_method; end
end
class Sub < Super; end
I would expect to be able to call Sub.super_singleton_method. However, in order to do this, Super.singleton_class needs to be somewhere in the method lookup chain of Sub.singleton_class.
So, for classes, the rule is somewhat different: the superclass of the singleton class of a class is the singleton class of the superclass of the class. I.e. for any class Foo, the following holds:
Foo.singleton_class.superclass == Foo.superclass.singleton_class
If you want, you can check whether this is true for every class in your system:
ObjectSpace.each_object(Class).select do |klass|
klass.singleton_class.superclass != klass.superclass.singleton_class
end
#=> [BasicObject]
So, as you can see, this property does hold for all classes except BasicObject.
The simple answer for why BasicObject is different is that BasicObject has no superclass, and thus we cannot apply the rule. So, we fall back on the more general rule for all objects that
foo.singleton_class.superclass == foo.class
And BasicObject's class is Class, therefore,
BasicObject.singleton_class.superclass == BasicObject.class
BasicObject.singleton_class.superclass == Class
and also why no other object in ruby have the Class class as its superclass?
The only reason to inherit from Class would be to override the behavior of how inheritance or method lookup works in Ruby. But Ruby does not allow to override this. How inheritance and method lookup works is part of the language specification and cannot be changed. Therefore, inheriting from Class is illegal:
class MyClass < Class; end
# can't make subclass of Class (TypeError)
Thus there cannot be any object which has Class as its superclass, except singleton classes of classes. (Ruby can of course break its own rules since it is the one that makes the rules.)
How the logic behind the superclass of singleton_class of BasicObject is implemented in Ruby?
It isn't. You cannot explain how this works in Ruby, since it is part of the definition of Ruby itself.
It is similar to how Class is a subclass of Module, but Module is a class, i.e. an instance of Class. You cannot explain this from within Ruby using the rules of Ruby, but the Ruby implementation can, of course, set things up so that this works, since the Ruby implementation itself does not have to abide by the rules of Ruby: it is the one enforcing the rules, so it can just choose not to enforce them for itself.
By definition, a singleton class of an object also inherits the singleton class of the superclass of the object.
Instead of taking this for granted, let's figure out why it was implemented this way.
In Ruby, there are instance methods and class methods. The class methods however are in fact instance methods of the singleton class:
class MyClass
def foo
end
def self.bar
end
end
MyClass.instance_methods(false)
#=> [:foo]
MyClass.singleton_class.instance_methods(false)
#=> [:bar]
As a diagram:
MyClass ---> #<Class:MyClass>
foo bar
Now, if you create a subclass MySubClass, it inherits both, the instance methods and the class methods from its superclass MyClass:
class MySubClass < MyClass
end
MySubClass.instance_methods
#=> [:foo, ...]
MySubClass.singleton_class.instance_methods
#=> [:bar, ...]
To get this working, the inheritance has to be established for both, the classes and the singleton classes:
MyClass ---> #<Class:MyClass>
foo bar
^ ^
| |
MySubClass ---> #<Class:MySubClass>
Ruby optimized this internally – the singleton classes are only created when needed. But conceptually, this is what happens.
Apart from that, MyClass and MySubClass already come with some built-in class methods, most notably .new which is used to create instances, but also .superclass.
You might know that the default implementation of .new calls .allocate under the hood. So somewhere there must be a sort of "root class" which contains these methods. And since they are class methods, it must sit on top of the singleton class side:
<singleton root class>
new
allocate
superclass
^
|
...
|
MyClass ---> #<Class:MyClass>
foo bar
^ ^
| |
MySubClass ---> #<Class:MySubClass>
And this mysterious top level singleton root class that provides the fundamental class methods for all other classes is ... Class!
Class.instance_methods(false)
#=> [:allocate, :superclass, :subclasses, :new]
As I understand ruby classes, they are almost the same as modules except with an added functionality of being able to instantiate it. As Class inherits from Module, I assumed that then every class (objects of class Class) would have access to module_function, but it does not seem to be the case. When I did a difference of Module and Class' private_instance_methods, I found that Module has 3 methods more than Class - [:append_features, :extend_object, :module_function]
How were these functions removed from the call chain for Class objects and more importantly why?
Those core features are implemented in C, so discussing about that does not have generality, and is not useful. Within Ruby, you can undefine an inherited method without undefining the method in the superclass by using undef.
class Foo
def foo; end
end
class Bar < Foo
undef :foo
end
Foo.new.foo
# => nil
Bar.new.foo
# => NoMethodError: undefined method `foo' for #<Bar:0x007f85c3ce3330>
append_features is a hook to be called right before a module is include-d, which a module can be, but not a class.
extend_object is a hook to be called right before a module is extend-ed, which a module can be, but not a class.
The purpose of module_function is to double the method as a class method and a private instance method, latter of which is useful when you include that module, which can be done with a module but not with a class.
Foo = Module.new
class MyClass
include Foo
end
When a module is included in a class, an anonymous proxy class is created and set as MyClass's superclass.
MyClass.ancestors => [MyClass, Foo, ...]
But what happens internally when a module is extended? How does Ruby handle this?
I think what you ask is Object#extend
So with extend, I can include any module's methods into that object.
For example I have a module called HelperModule:
module HelperModule
def foo
puts "from module helper"
end
end
Usage Example 1:
obj = Object.new
obj.extend HelperModule
obj.foo # => "from module helper"
Usage Example 2:
class MyClass
extend HelperModule
end
MyClass.foo # => "from module helper"
Internally, according to Metaprogramming Ruby:
Object#extend() is simply a shortcut that includes a module in the receiver’s eigenclass.
A brief explanation of ruby's methods call :
find the object's class, see if the method defined there
find that class's superclass, see if the method defined there
obj
|
| class
| superclass superclass
---> ObjectClass --------------> SuperClass1 --------------> SuperClass2 ....
The detailed explanation about eigenclass and method call path, please reference this awesome book Metaprogramming Ruby
Thanks
Whats happens internally when a module in extended in Ruby?
When a module M is included in a class C, an anonymous proxy class ⟦M′⟧ (called an include class) is created such that its method table pointer points to M's method table. (Same for the constant table and module variables.) ⟦M′⟧'s superclass is set to C's superclass and C's superclass is set to ⟦M′⟧.
Also, if M includes other modules, the process is applied recursively.
Actually, that's just the default behavior. What really happens is that include calls M.append_features(C), and you can customize all of that behavior by overriding that method.
I find the source code of Module#append_features in Rubinius quite readable.
obj.extend SomeModule is the same as obj.eigenclass.include SomeModule (Note: this is just pseudocode, but you will get the idea...).
In a nutshell, Ruby's include method will emulate inheritance: it will allow the including class access to the included module's instance methods, variables and constants as if they had been defined in the including class itself. Ruby does this by creating an anonymous proxy class (known as an eigenclass or singleton class), as you mentioned, which references the included module, and inserting it into the ancestors of the including class as the immediate superclass. This is what is known as a mixin in Ruby.
Using extend, however, interacts with the singleton class a little bit more:
module Foo
def baz
'baz'
end
end
module Blah
def blah
'blah'
end
end
class Bar
extend Foo
include Blah
def self.magic
'magic'
end
end
Extending Foo in Bar is identical (right down to its implementation in C) to saying
Bar.singleton_class.send( :include, Foo )
This means that it is the singleton class of Bar in which the methods and constants of Foo are essentially embedded, and thus class Bar, being an instance of its singleton class, will inherit this new functionality as so-called 'class' methods. In Ruby, modules and classes can only have instance methods, and thus the creation of a 'class' method will actually just create an instance method in the class's singleton class, to be inherited in this manner.
Bar.baz
# => 'baz'
Bar.magic
# => 'magic'
Bar.blah
# => NoMethodError
Bar.new.baz
# => NoMethodError
Bar.new.magic
# => NoMethodError
Bar.new.blah
# => 'blah'
Here you can see the differences in behavior of include and extend. To verify their behavior with regards to class ancestry, you can ask for the ancestors of Bar and its singleton class, and it will show you that module Blah is the immediate parent of Bar, but module Foo is the immediate parent of the singleton class.
Bar.ancestors
# => [Bar, Blah, Object, Kernel, BasicObject]
Bar.singleton_class.ancestors
# => [Foo, Class, Module, Object, Kernel, BasicObject]
From these results, you can see how inclusion emulates inheritance in the including class, and how extension is merely inclusion within the singleton class.
You might try looking at the answers I got for this question awhile back; they did an excellent job of explaining the behavior of the include and extend functionality.
This article has also helped me understand their differences.
class Person
def name
puts "Dave"
end
end
puts Person.object_id
There are only two ways of accessing methods :
1) Someclass.method in case of class methods. #where Someclass is a class.
2) and Object.method when the method being accessed is a regular method declared inside a class. and Object is an instance of a class.
It follows the pattern Object.method so, does it mean Person class is really an object?
or object_id is a class method? The latter seems unlikely because class methods cannot be inherited into an instance. but when we do something like this :
a = Person.new
a.methods.include?("object_id") # this produces true
a is an instance of Person class so object_id cannot be a class method.
Yes, Ruby classes are objects:
>> String.is_a? Object
=> true
>> String.methods.count
=> 131
>> Fixnum.methods.count
=> 128
Yes, classes in Ruby are instances of class Class. In fact, you can create the same class just with:
Person = Class.new do
define_method :name do
puts 'Dave'
end
end
Then, you can just type Person.new.name and it will work exactly as your class.
Checking that Person is an instance of class Class is as easy as typing in your repl Person.class and you get Class in return.
I am but confused right now after writing my repeated efforts at understanding the object model of ruby : following are my observations.
class Bird
def speak
puts "tweet tweet"
end
end
>> Bird.class
=> Class
>> Class.class
=> Class
>> Class.superclass
=> Module
>> Module.class
=> Class
>> Module.superclass
=> Object
>> Object.class
=> Class
>> Object.superclass
=> nil
>> nil.class
=> NilClass
>> NilClass.class
=> Class
>> NilClass.superclass
=> Object
and keeps going on ....
What is going on here ? What lies at the apex of ancestry nil or NilClass or Object or Class ? How is Ruby's Object Model Organized.
What is a class and what is a object ? is Class a class or an object ? is Object an Object or a class ?
In ruby, a class object, is actually an instance of the Class class. class Foo is nearly identical to Foo = Class.new
MyClass = Class.new
instance = MyClass.new
puts instance # => #<MyClass:0x100c14b38>
Also, the class method is more design to be called on instances, not class objects.
class Foo
end
f = Foo.new
puts f.class # => Foo
The semantics can be odd when calling on class objects. Though superclass works as you would expect on a class object.
So given all that lets explain these one by one:
>> Bird.class
=> Class
Bird the class object has a class of Class, since all class objects are instances of the Class class.
>> Class.class
=> Class
Yep even Class is an instance of Class. In this case it's actually a circular reference.
>> Class.superclass
=> Module
The Class class actually inherits from Module. After all, a class is simply a module that can be instantiated. But all non-instance functionality is pretty identical to modules.
>> Module.superclass
=> Object
Module inherits from Object. Just like everything in ruby if you go back far enough.
>> Object.class
=> Class
Again all class objects are instances of Class.
>> Object.superclass
=> nil
All ruby everything starts with Object. It is the base class for everything. Therefore it has no superclass.
>> nil.class
=> NilClass
nil is actually an instance of NilClass under the hood. NilClass defines methods that nil responds to. You can even add methods to NilClass if you want. There is also a TrueClass and a FalseClass.
>> NilClass.class
=> Class
Again all class objects are instances of Class.
>> NilClass.superclass
=> Object
NilClass inherits from Object like any class that does not specify an explicit superclass.
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.
You can conclude the following from your example:
Every name written in uppercase that appears in your example script points to a class (Bird, Class, Module, Object, NilClass).
Every class is in turn an object of type Class (this is why X.class always returns Class in your example).
X.superclass returns the base class of X.
Object.superclass returns nil, because it has no base class! This does NOT mean that the base class of Object is NilClass or even nil (which is not a type, but an instance)
The inheritance diagrams of the involved classes look something like:
Object (top-level) Object Object
| | |
Module Bird NilClass
|
Class
Class returns a class for an object (and a class is an object). Superclass is the parent class of a (derived) class.
Please, see the Ruby Object Model.
I think you're getting confused about the difference between instances (like nil) and classes (like NilClass). It's reasonable to find it confusing because Ruby classes (NilClass) are also instances. Thus: a class is an instance. An instance is not a class though unless it is a class.
Here's a detailed hierarchy, which is made by ObjectGraph.