In Metaprogramming Ruby book, I can across the concept of superclass and class.
Here is the reference image:
As I understand: Class has an instance method defined superclass , which can be called by any new class defined (Here MyClass)
My question is:
The parent Class has superclass as Module but the object MyClass has superclass as Object . Why does superclass of Myclass is Object but not Module ? If it is by design, why is it designed this way?
If you define a new class Foo in Ruby, then indeed, it is an instance of Class class, and Foo.class.superclass is Module as expected. But since you are asking not about the ancestors of Foo.class, but directly about the ancestors of Foo, then know that
class Foo
end
is the same as writing
class Foo < Object
end
In other words, a newly defined class will by default become a subclass of Object class, unless otherwise specified. Of course, you could manually define
class Bar < Module
end
in order to create an explicit subclass of Module class. Descendants of Module class have specific qualities and are of special use in Ruby. Note that class Class cannot be subclassed.
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.
How is it that this works? When the following is run "hi from class" is printed twice. What is going on inside ruby to make this behave like this? Am I NOT in fact making an instance method for class
class Class
def foo
puts "hi from class"
end
end
Class.foo
x = Class.new
x.foo
I don't know whether you're aware of that, but when you do class Class ... end, you're not creating a new class named Class, you're reopening the existing class Class.
Since Class is the class that all classes are instances of that means that Class is an instance of itself. And because of that you can call any instance methods of Class directly on Class the same way you can on any other class.
Object , Class, Module , NilClass are all instances of Class.
1) First Doubt how can something be an instance of itself ? (i.e 'Class' is an instance of 'Class') or is my assumption wrong ?
2) If Object , Class ,Module etc ... are all objects then how can they have class methods ? Because class methods can only be called from classes and are not present in objects. (or is my assertion incorrect that Object, Class , Module are all objects ?)
3)If Object , Class , Module are not objects then what are they ?
3) Does a class method account for the missing method in instance a of Class and ultimately a decrease in method count ?
>> Class.methods.count
=> 82
>> a = Class.new
=> #<Class:0x1005519b8>
>> a.methods.count
=> 81
Class objects are indeed objects.
Class methods are actually methods defined in the class's eigenclass (singleton class). That is why those methods are not available to actual instances of said classes.
Here's a way to help you see this: first, add a singleton_class method if you don't already have it:
module Kernel
def singleton_class
class << self
self
end
end
end
Now, try the following:
String.instance_methods
String.singleton_class.instance_methods
Class.instance_methods
Class.singleton_class.instance_methods
c = Class.new
c.instance_methods
c.singleton_class.instance_methods
This will help you gain an appreciation for what methods are available to instances of a class, versus what methods are methods on the class (i.e., instances of the class's singleton class).
(You can pass a false argument to each of those instance_methods calls to see which methods are defined for that class, and not any superclasses.)
The Ruby core is composed by Class, Object, Module and Kernel. They're predefined, so the Class class can be an instance of itself.
They have class methods because they're classes, too (and classes are objects).
I can't answer it yet. I have to discover which method is missing to think in an answer.
If a class has been previously defined how can I tell it to inherit from a class Parent
For instance:
class Parent
..
end
class Klass
..
end
Now I want it to inherit from Parent
I cant re-open the class and set it because I will get a class mismatch error
class Klass < Parent
..
end
Specifically I am trying to find out how to set the class inheritance on a class im creating through Object.const_set
klass = Object.const_set('Klass', Class.new)
How can I tell Klass to inherit from class Parent?
There is no way to change the superclass of an already existing class.
To specifiy the superclass of a class you're creating dynamically, you simply pass the superclass as an argument to Class.new.
class Parent
end
klass = Class.new(Parent)
klass.superclass #=> Parent
Just as a side note: You're not creating the class with const_set. You're creating it with Class.new. You're simply storing the created class in a constant with const_set. Once const_set is invoked, Class.new has already happened and the superclass cannot be changed anymore.