NilClass - What does Ruby inheritance really mean? - ruby

Newbie question.
I assumed that "inheritance" is the basic feature of Ruby. And every class inherits methods from both its .class and .superclass.
Since NilClass has Class and Object as its .class and .superclass, you'd assume NilClass to have all their methods.
Then my brain exploded when I saw this:
>> NilClass.class
=> Class
>> NilClass.class.methods - NilClass.methods
=> [:nesting, :new]
>> NilClass.superclass
=> Object
>> NilClass.superclass.methods - NilClass.methods
=> [:new]
What is going on?
Can anyone explain what's really going on underlying the whole inheritance mechanism in Ruby?
What does inheritance really mean in Ruby?

I assumed that "inheritance" is the basic feature of Ruby. And every class inherits methods from both its .class and .superclass.
That's correct. Every class inherits methods from its superclass, which is Object by default.
class Foo
end
Foo.superclass #=> Object
Foo responds to Object's class methods and Foo instances respond to Object's instance methods.
Furthermore, every class is an instance of Class and therefore responds to Class' instance methods (just like Foo instances respond to Foo's instance methods):
Foo.class #=> Class
Foo.method(:new)
#=> #<Method: Class#new>
Calling Foo.new simply invokes Class#new.
Since NilClass has Class and Object as its .class and .superclass, you'd assume NilClass to have all their methods.
It would, but nil is a singleton, i.e. there's only one nil instance and you can't create any other instances. This is achieved (among other things) by undefining new. From Ruby's source code:
rb_undef_method(CLASS_OF(rb_cNilClass), "new");
You could do the same in plain Ruby:
Foo.singleton_class.send(:undef_method, :new)
Foo.new
#=> NoMethodError: undefined method `new' for Foo:Class

Related

What is a singleton class in Ruby?

I m having trouble understanding the concept of eigenclass or singleton class in ruby. I read a lot that the eigenclass is a class's class. That doesn't make sense to me as for me a class's class is actually Class as all classes are actually instances of the class Class.
Another thing I don't quite get is the following statement: a class method is actually an instance method of the class eigenclass. The eigenclass is accessible this way :
YourClass = Class.new
class << YourClass
def class_method
end
end
But if the eigenclass is indeed the YourClass class (that is Class), shouldn't the preceding piece of code open the class Class and add to it the instance method class_method making it accessible to all of its future instances (that is any regular class defined in the future)?
I actually kind of feel that the singleton class is not the same as Class. When you do :
class MyClass
end
MyClass.singleton_class
you get #<Class:MyClass> which is different from the output of MyClass.class => Class
What is that #<Class:MyClass> output ? This has nothing to do with namespace as otherwise there would be two: Class::MyClass...
I'm Looking for a simple and unambiguous explanation of the eigenclass concept in order to clarify my ideas.
Singleton classes hold methods that are specific to a single object.
For generic objects, it's a nice-to-have feature. But for classes, it's crucial. Let's start with the objects:
Singleton classes for objects
Instance methods are usually defined in classes. All instances of the same class share the same instance methods. The singleton class sits between the object and its class. It allows each instance to have its own set of methods, independent of the other instances.
If we have two classes, Foo and Bar with 2 instances each a, b and c, d:
class Foo ; end
class Bar ; end
a = Foo.new #=> #<Foo:0x00007fc280963008>
b = Foo.new #=> #<Foo:0x00007f8319016b18>
c = Bar.new #=> #<Bar:0x00007fa66c8d7290>
d = Bar.new #=> #<Bar:0x00007f94d5106ac8>
You would have this class structure: (simplified, excluding modules)
object singleton class class superclass ...
a ── #<Class:#<Foo:0x00007fc280963008>> ─┐
├─ Foo ─┐
b ── #<Class:#<Foo:0x00007f8319016b18>> ─┘ │
├─ Object ── BasicObject
c ── #<Class:#<Bar:0x00007fa66c8d7290>> ─┐ │
├─ Bar ─┘
d ── #<Class:#<Bar:0x00007f94d5106ac8>> ─┘
Ruby creates those singleton classes lazily, for example when calling singleton_class.
So when defining a method a.hello, it is not stored in a's class Foo, but in a's singleton class:
def a.hello
'hello from a'
end
a.method(:hello).owner
#=> #<Class:#<Foo:0x00007fc280963008>> <-- a's singleton class
Because of that, b doesn't see that method, even though both are Foo instances:
b.hello #=> NoMethodError: undefined method `hello'
And we can even define a method with the same name for b without interfering with a:
def b.hello
'hello from b'
end
b.method(:hello).owner
#=> #<Class:#<Foo:0x00007f8319016b18>> <-- b's singleton class
a.hello #=> "hello from a"
b.hello #=> "hello from b"
We could also define a generic hello in Foo and override it on a per instance level: (you usually don't do that, but it's possible)
class Foo
def hello
'hello'
end
end
def a.hello
"#{super} from a"
end
def b.hello
"b says #{super.upcase}!"
end
a.hello #=> "hello from a"
b.hello #=> "b says HELLO!"
c = Foo.new
c.hello #=> "hello"
Singleton classes for classes
The above is especially important for classes. Each class is an instance of Class:
Foo.class #=> Class
Let's say we wanted to have a method Foo.hello, where would we define it?
Instance methods are usually defined in the instance's class, so we could define it in Foo's class:
class Class
def hello
'Hello from Foo'
end
end
Foo.hello
#=> "Hello from Foo"
But that would make the method available to all instances of Class:
Bar.hello
#=> "Hello from Foo"
String.hello
#=> "Hello from Foo"
It would be better to have a place that's exclusive to the Foo instance. And that place is Foo's singleton class:
def Foo.hello
'Hello from Foo'
end
or
class Foo
def self.hello # <-- self is Foo, so this is just "def Foo.hello"
'hello from Foo'
end
end
Just like a.hello above, this method is only available to Foo:
Foo.hello #=> "hello from Foo"
Bar.hello #=> NoMethodError
We call these methods class methods, but they are really just instance methods of the singleton class:
Foo.method(:hello).owner
#=> #<Class:Foo> <-- Foo's singleton class
Foo.method(:hello).unbind == Foo.singleton_class.instance_method(:hello)
#=> true
And if you compare the singleton methods for classes with those for objects, you'll see that they are identical. That's because in Ruby, classes are objects too, and all objects work alike.
I think you're getting a bit off track by confusing the idea of the eigenclass with the idea of a Ruby class instance. They aren't exactly the same; it's more correct to say that Ruby implements class definitions internally as two objects.
This is easily enough demonstrated:
$ irb
> ObjectSpace.count_objects[:T_CLASS]
=> 1285
> Foo = Class.new { def instance_method; end }
=> Foo
> ObjectSpace.count_objects[:T_CLASS]
=> 1287
Internally, every object has a klass pointer, which on the surface points to the class the object is an instance of. However, every object (except certain primitives such as Integer, Float and Symbol) also has an eigenclass instance, and this is what the klass pointer actually points to. In the case of classes, then, the klass pointer doesn't actually point to the Class class, but to the singleton object that's part of the class definition, and that contains the method table that holds the class methods.
As the link that anothermh provides explains, the "ordinary" class object's method table contains all the class's instance methods, while the eigenclass object's method table contains all of the class's class methods. This is the mechanism that prevents all of the class's class methods from being accessible to any instance of the Class class.
Now, the eigenclass (eigen is German for "own" in the sense of "my own") is the class of the class, which is why it's also called a metaclass. (Have a look at the source code for Class::new and you will see a call to rb_make_metaclass.)
This is why a call to MyClass.singleton_class returns #Class:MyClass rather than Class as a call to MyClass.class does. This syntax is analogous to p Foo.new returning something like #<Foo:0x00007f9c0d190400>, which is the class and the pointer to the instance. With #Class:MyClass, MyClass is the pointer to the instance. So, this describes a reference to MyClass's metaclass, or the class of MyClass. This is not to be confused with what class MyClass is an instance of, which, of course, is Class.
In case you're curious, the klass pointer in the eigenclass instance actually points to itself. This is demonstrated by the fact that MyClass.singleton_class.singleton_class returns #Class:#Class:MyClass.
For a more comprehensive overview, see Demystifying Ruby Singleton Classes. For a look at what's going on in the source code, see The Ruby Hacking Guide: Chapter 4. Finally, Ruby Under a Microscope is an excellent resource for a comprehensive deep dive into Ruby internals.
[Edited to incorporate some of the discussion in comments]
Eigenclass is no longer a name used in the Ruby world because Ruby officially introduced a method Object#singleton_class in I don't know which version (sorry).
Every object in Ruby, being a "normal" object or a class, or even a singleton class, has its own singleton class.
A singleton class is a class.
Object.new.singleton_class.is_a?(Class) #=> true
A singleton class has and only has one instance, and it's the object you call singleton_class on. e.g. the only instance of foo.singleton_class is foo.
Ruby allows you to add methods to individual objects.
a = Object.new
b = Object.new
def a.foo
'foo'
end
a.foo #=> "foo"
b.foo #=> raises NoMethodError
But all instance methods should be defined in a class, so in which class is a.foo defined? The answer is a.singleton_class. Because a.singleton_class only has one instance that is a, the instance method foo can only be called on a, not on b, though they are of the same type.
As for the class's singleton classes, their purpose is to store the "normal classes'" class methods, or if you twist your brain a little, the instance methods that are bound to the individual class instances.
Don't you feel Ruby's object model consistent and beautiful?

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.

Get Ruby class name without class method

How can I get the class name of an instance of BasicObject in Ruby? For example, say I have this:
class MyObjectSystem < BasicObject
end
puts MyObjectSystem.new.class
How can I make this code succeed?
EDIT: I've found that Object's instance method class is defined as return rb_class_real(CLASS_OF(obj));. Any way to use this from Ruby?
I spent some time playing around with irb and came up with this:
class BasicObject
def class
klass = class << self; self; end # get the object's singleton class
klass.superclass # the superclass of an object's singleton class is that object's class
end
end
That will give any object that inherits from BasicObject a #class method that you can call.
Edit
Further explanation as requested in the comments:
Say you have object obj that is an instance of class Foo. obj gets its instance methods from those that are defined within the class Foo, in addition to the methods defined in Foo's parent class and so on up the inheritance chain. Ruby lets you define methods directly on an object that are only accessible to that particular object like this
obj = Foo.new
def obj.hello
puts "hello"
end
obj.hello #=> hello
other_obj = Foo.new
other_obj.hello #=> Method missing error
The reason you can do this is because every object has something called a singleton class (or sometimes call an eigenclass) that you are actually defining the method on. This singleton class actually exists in the inheritance chain of the object directly beneath the object's actual class. That makes the object's actual class, Foo in this example, the superclass of the object's singleton class.
The class << self line you see in the answer is a special syntax for entering the scope of an object's singleton class. So in the example above, you could also define a method in an object's singleton class like this
class << obj
def goodbye
puts "goodbye"
end
end
obj.goodbye #=> goodbye
So the line class << self; self; end is opening the object's singleton class (whatever object is currently self) and then returning self (self has now become the singleton class), which can then be assigned to a variable to do what you wish with.
I would recommend reading Metaprogramming Ruby if you want a better explanation of all this. It definitely gives you a much better understanding of the Ruby object model as a whole.
I have to leave in a few minutes so I can't test it myself, but it seems like you could make a separate module that uses ffi to call rb_class_real from libruby. If I had more time I would test it first, but nobody else has answered yet and I don't want you leave you totally out in the cold.
Based on Jeff Smith's answer, you can do this without modifying BasicObject:
class << object; self; end.superclass
where object is an instance of an object whose class you want, i.e.,
irb(main):001:0> object = BasicObject.new
(Object doesn't support #inspect)
=>
irb(main):002:0> class << object; self; end.superclass
=> BasicObject

What is the difference between type of a class and superclass of a class in ruby?

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.

Extending classes and instances

This question has two parts.
In the Ruby Programming Language book, there is an example (section 8.1.1) of extending a string object and class with a module.
First question. Why is it that if you extend a class with a new method, and then create an object/instance of that class, you cannot access that method?
irb(main):001:0> module Greeter; def ciao; "Ciao!"; end; end
=> nil
irb(main):002:0> String.extend(Greeter)
=> String
irb(main):003:0> String.ciao
=> "Ciao!"
irb(main):004:0> x = "foo bar"
=> "foo bar"
irb(main):005:0> x.ciao
NoMethodError: undefined method `ciao' for "foo bar":String
from (irb):5
from :0
irb(main):006:0>
Second part, When I try to extend a Fixnum object, I get an undefined method error. Can someone explain why this works for a string but not a fixnum?
irb(main):045:0> module Greeter; def ciao; "Ciao!"; end; end
=> nil
irb(main):006:0> 3.extend(Greeter)
TypeError: can't define singleton
from (irb):6:in `extend_object'
from (irb):6:in `extend'
from (irb):6
First question. Why is it that if you
extend a class with a new method, and
then create an object/instance of that
class, you cannot access that method?
Because you extended the String class, so #ciao is a class method and not an instance method.
String.send(:include, Greeter)
x = "foo bar"
x.ciao
# => "Ciao!"
Second part, When I try to extend a
Fixnum object, I get an undefined
method error. Can someone explain why
this works for a string but not a
fixnum?
Here's the short answer.
"Fixnums, Symbols, true, nil, and
false are implemented as immediate
values. With immediate values,
variables hold the objects themselves,
rather than references to them.
Singleton methods cannot be defined
for such objects. Two Fixnums of the
same value always represent the same
object instance, so (for example)
instance variables for the Fixnum with
the value "one" are shared between all
the "ones" is the system. This makes
it impossible to define a singleton
method for just one of these."
Off course, you can include/exten the Fixnum class and every Fixnum instance will expose the methods in the Mixin.
This is exactly what Rails/ActiveSupport does in order to allow you to write
3.days.ago
1.hour.from_now
obj.extend(module) adds all the methods in module to obj. When called as String.extend(Greeter) you are adding the methods from Greeter to the instance of Class that represents String.
The easiest way to add additional instance methods to an existing class is to re-open the class. The following examples do the same thing:
class String
include Greeter
end
class String
def ciao
"Ciao!"
end
end
Fixnums (as well as Symbols, true, false and nil) are handled in a different way to normal instances. Two Fixnums with the same value will always be represented by the same object instance. As a result, Ruby doesn't allow you to extend them.
You can of course extend an instance of any other class, e.g.:
t = "Test"
t.extend(Greeter)
t.ciao
=> "Ciao!"

Resources