Ruby mixins: extend and include - ruby

I've been reading a few articles about Ruby's mixin methods, extend and include, and I am still not quite sure about the behavior. I understand that extend will add the instance methods of the given module as singleton methods to the module doing the extending, and that include will essentially append the contents of a module (methods, constants, variables) to the one doing the including, effectively defining them in the receiver.
However, after some tinkering, trying to get a feel for how the behavior will manifest, I've got a few questions. Here is my testing setup:
module Baz
def blorg
puts 'blorg'
end
end
module Bar
include Baz
def blah
puts 'blah'
end
end
module Foo
extend Bar
end
class Bacon
extend Bar
end
class Egg
include Bar
end
So as I would expect, module Bar gains the instance methods defined in Baz (#blorg) as if they'd been defined in itself due to the inclusion method, and class Bacon gains the singleton methods Bacon::blah and Bacon::blorg by extension.
Bacon.blah # => blah
Bacon.blorg # => blorg
And class Egg gains the methods defined in Bar (#blah and now #blorg) as instance methods.
Egg.new.blah # => blah
Egg.new.blorg # => blorg
I get all that, so that's good.
However, I don't understand the responses I get from using the #ancestors and #is_a? methods.
Bacon.ancestors # => [Bacon, Object, Kernel, BasicObject]
Bacon.is_a? Bar # => true
Egg.ancestors # => [Egg, Bar, Baz, Object, Kernel, BasicObject]
Egg.is_a? Bar # => false
It would seem that extending a module causes the #is_a? method to return true when queried about that module, but it is not added to the ancestors of the class, and vice versa with regards to inclusion: the ancestors of the class contains the modules being included, but the #is_a? method returns false when queried. Why does this happen?

The difference is that include will add the included class to the ancestors of the including class, whereas extend will add the extended class to the ancestors of the extending classes' singleton class. Phew. Let's first observe what happens:
Bacon.ancestors
#=> [Bacon, Object, Kernel, BasicObject]
Bacon.singleton_class.ancestors
#=> [Bar, Baz, Class, Module, Object, Kernel, BasicObject]
Bacon.new.singleton_class.ancestors
#=> [Bacon, Object, Kernel, BasicObject]
Bacon.is_a? Bar
#=> true
Bacon.new.is_a? Bar
#=> false
And for the Egg class
Egg.ancestors
#=> [Egg, Bar, Baz, Object, Kernel, BasicObject]
Egg.singleton_class.ancestors
#=> [Class, Module, Object, Kernel, BasicObject]
Egg.new.singleton_class.ancestors
#=> [Egg, Bar, Baz, Object, Kernel, BasicObject]
Egg.is_a? Bar
#=> false
Egg.new.is_a? Bar
#=> true
So what foo.is_a? Klass actually does is to check whether foo.singleton_class.ancestors contains Klass. The other thing happening is that all the ancestors of a class become ancestors of an instances' singleton class when the instance is created. So this will evaluate to true for all newly created instances of any class:
Egg.ancestors == Egg.new.singleton_class.ancestors
So what does all this mean? extend and include do the same thing on different levels, i hope the following example makes this clear as both ways to extend a class are essentially equivalent:
module A
def foobar
puts 'foobar'
end
end
class B
extend A
end
class C
class << self
include A
end
end
B.singleton_class.ancestors == C.singleton_class.ancestors
#=> true
where class << self is just the odd syntax to get to the singleton class. So extend really just is a shorthand for include in the singleton class.

Egg.is_a? Egg # => false
The include (effectively) changes instances of the Egg class. Although it isn't quite the same, it is very similar to doing something like
class Egg < Bar
end
When the extend will add class methods, so this is very similar to doing something like
class Bacon
class << self
include Bar
end
end
You can think of it like include changes instances of the class, where as extend actually changes the class.

Related

Ruby: Are these two methods of mixing-in module methods equivalent?

I have a module and a class.
module Dog
def speak
"woof"
end
end
class Daschund; end
I create two separate instances of the class.
sausage = Daschund.new
saveloy = Daschund.new
If I want to add Dog#woof as an instance method of my two new objects, I can do it in two ways:
class << sausage
include Dog
end
> sausage.speak
=> "woof"
saveloy.extend Dog
> saveloy.speak
=> "woof"
Are the two methods equivalent? I know the first adds the module's method to the object's meta-class. Does object#extend do the same thing? Or is it doing something slightly different? Is there any way to prove this?
According to the docs for Object, extending an object with a module means including that module to the object's singleton class:
extend: Includes the given modules in the singleton class of self.
Inspecting the ancestors of both objects' singleton classes confirms this:
sausage.singleton_class.ancestors
#=> [#<Class:#<Daschund:0x00007fa6af92e868>>, Dog, Daschund, Object, Kernel, BasicObject]
saveloy.singleton_class.ancestors
#=> [#<Class:#<Daschund:0x00007fa6af92e778>>, Dog, Daschund, Object, Kernel, BasicObject]
The actual implementation details of course depend on the Ruby implementation and version you are using. For MRI/YARV, you have rb_extend_object defined as:
void
rb_extend_object(VALUE obj, VALUE module)
{
rb_include_module(rb_singleton_class(obj), module);
}

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?

Methods defined in class Object are instance and class one at the same time

How can be described that a method boo defined in Object class becomes instance and class one at the same time in class Foo?
class Foo; end
class Object
def boo
'boo method'
end
end
p Foo.boo # => boo method
p Foo.new.boo # => boo method
Every object is an instance of Object. Thus, every object will respond to boo.
Foo is an object (classes are objects, too), ergo, Foo is an instance of Object (it is an instance of Class, which is a subclass of Module, which is a subclass of Object).
Foo.new is an object (it is an instance of Foo, which is a subclass of Object).
Since both Foo and Foo.new are instances of Object, both respond to boo.
[Note: I am ignoring the existence of BasicObject.]
If you really want to do this, keep in mind that the class context and the instance context are entirely different so instance variables are not equivalent.
module FooMethods
def boo
'boo'
end
end
class Foo
extend FooMethods
include FooMethods
end
This deliberately imports the mixin at both the class level via extend and instance level via include.
Perhaps forwarding the method to self is an option?
require 'forwardable'
class Foo
extend Forwardable
def self.boo
'boo method'
end
def_delegator self, :boo
end
Foo.boo
#=> "boo method"
Foo.new.boo
#=> "boo method"

What happens internally when a module is extended in Ruby?

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.

Where are methods defined at the ruby top level?

At the top level, method definition should result in private methods on Object, and tests seem to bear this out:
def hello; "hello world"; end
Object.private_instance_methods.include?(:hello) #=> true
Object.new.send(:hello) #=> "hello world"
However, the following also works at top level (self.meta is the eigenclass of main):
self.meta.private_instance_methods(false).include?(:hello) #=> true
It appears that the hello method is simultaneously defined on the eigenclass of main as well as on Object. What's going on? Note that the false parameter to private_instance_methods excludes super class methods from the method list.
First of all, this behavior and the underlying reasoning have always existed; it's nothing new to 1.9. The technical reason it happens is because main is special and treated differently than any other object. There's no fancy explanation available: it behaves that way because it was designed that way.
Okay, but why? What's the reasoning for main to be magical? Because Ruby's designer Yukihiro Matsumoto thinks it makes the language better to have this behavior:
Is so, why are top-level methods not made singleton-methods on this object,
instead of being pulled in as instance methods on the Object class
itself
(and hence into all other classes i.e. more namespace pollution than is
usually intended). This would still allow top-level methods to call other
top-level methods. And if the top-level object were referred to by
some
constant like Main, then those methods could be called from anywhere
with
Main.method(...).
Do you really wish to type
"Main.print" everywhere?
Further on in the discussion, he explains that it behaves this way because he feels the "assumption is natural."
EDIT:
In response to your comment, your question is aimed at why main's eigenclass seems to report hello as a private instance method. The catch is that none of the top-level functions are actually added to main, but directly to Object. When working with eigenclasses, the instance_methods family of functions always behave as if the eigenclass is still the original class. That is, methods defined in the class are treated as being defined directly in the eigenclass. For example:
class Object
private
def foo
"foo"
end
end
self.send :foo # => "foo"
Object.private_instance_methods(false).include? :foo # => true
self.meta.private_instance_methods(false).include? :foo # => true
class Bar
private
def bar
"bar"
end
end
bar = Bar.new
bar.send :bar # => "bar"
Bar.private_instance_methods(false).include? :bar # => true
bar.meta.private_instance_methods(false).include? :bar # => true
We can add a method directly to main's eigenclass, though. Compare your original example with this:
def self.hello; "hello world"; end
Object.instance_methods.include? :hello # => false
self.meta.instance_methods.include? :hello # => true
Okay, but what if we really want to know that a given function is defined on the eigenclass, not the original class?
def foo; "foo"; end #Remember, this defines it in Object, not on main
def self.bar; "bar"; end #This is defined on main, not Object
foo # => "foo"
bar # => "bar"
self.singleton_methods.include? :foo # => false
self.singleton_methods.include? :bar # => true

Resources