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

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);
}

Related

Ruby’s secret trick to avoid “class methods” and keep its type system simple and elegant

From Wikibooks' Ruby Programming/Overview:
When I said that every Ruby object has a class, I lied. The truth is, every object has two classes: a “regular” class and a singleton class. An object’s singleton class is a nameless class whose only instance is that object. Every object has its very own singleton class, created automatically along with the object. Singleton classes inherit from their object’s regular class and are initially empty, but you can open them up and add methods to them, which can then be called on the lone object belonging to them. This is Ruby’s secret trick to avoid “class methods” and keep its type system simple and elegant
The above passage says that Ruby's secret trick to avoid class methods. I don't understand what the author means here. Where is Ruby stopping us to avoid class methods? for an example, look at the example shown below
class Raj
def self.hi
puts 'Hi'
end
def hello
puts 'hello'
end
end
object=Raj.new
object.hello
Raj.hi
As you can see in the preceding example, the class methods can still be created.
yes?
I understand that there are no true class methods in Ruby; instead, they are methods that are created for the Raj object.
But, in any case, it's allowing me to create the method 'hi,' right?
So, what does it mean when it says, 'This is Ruby's secret trick for avoiding "class methods" and keeping its type system simple and elegant'?
I understand that there are no true class methods in Ruby; instead, they are methods that are created for the Raj object.
That's exactly it, though.
def self.hi
puts 'Hi'
end
This is not a class method or static method. Those don't exist in Ruby. That's the whole point. Your class Raj defines an object of type Class. We can see its type with the #class function.
> Raj.class
=> Class
We can also see its ancestors.
> Raj.class.ancestors
=> [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
Class inherits from Module, since (for the most part) classes can do everything modules can. Module, in turn, inherits from Object, which has some modules of its own mixed in (PP:ObjectMixin is for pretty-printing, and Kernel gets you the nice helpers like puts) and eventually inherits from the root class BasicObject.
But this isn't the whole story, for Raj has its own class as well: its singleton class. We can see the full story by calling #singleton_class instead of #class.
> Raj.singleton_class.ancestors
=>
[#<Class:Raj>,
#<Class:Object>,
#<Class:BasicObject>,
Class,
Module,
Object,
PP::ObjectMixin,
Kernel,
BasicObject]
Now there's a lot more going on. Raj is an instance of the singleton class of Raj, which inherits from the singleton class of Object, which in turn inherits from the singleton class of BasicObject, which inherits from Class and all of the stuff we saw before.
So when you define a method on the class Raj, you're defining it (as an instance method) on the singleton class #<Class:Raj>. And that class (currently) has one instance: Raj.
By the way, it's also useful to know that the term "singleton class" is a bit of a lie. As you can see, the class is very much not a singleton in general. For instance, the singleton class of Object, called #<Class:Object> above, actually has several instances: Object, Raj, String, and most Ruby classes. Personally, I prefer to call them eigenclasses for that reason, but "singleton class" is the official (and more well-known) term.
The author is talking about the singleton class in this sentence, there is a really nice article to deep dive into ruby singleton class: https://medium.com/#leo_hetsch/demystifying-singleton-classes-in-ruby-caf3fa4c9d91
Here is a nice example extracted from this article:
class Vehicle
def initialize(kms)
#kms = kms
end
def drive
puts "let's go!"
end
end
car = Vehicle.new(1000)
bus = Vehicle.new(3000)
def car.drive
print "I'm driving a car! "
super
end
car.drive # "I'm driving a car! let's go!"
bus.drive # "let's go!"
As you can see, here the #drive method has been overridden but only for the car object, the bus object is still using the #drive method defined in the Vehicle class.
This new method is defined on the singleton class (or shadow class) of the object, this is allowing you to define new methods on the fly on an object without polluting all the objects of this class.
This means that Ruby doesn't implement class methods.
Indeed, the Ruby OBJECT Model, allows you to "emulate" the definition of class methods by defining instance methods on the Eigenclass:
class Greeting
def self.hello
'hello world!'
end
def self.eigenclass
class << self
self
end
end
end
Greeting.eigenclass # => #<Class:Greeting>
Greeting.eigenclass.name # => nil
Greeting.singleton_methods # => [:hello, :eigenclass]
Greeting.eigenclass.instance_methods(false) # => [:hello, :eigenclass]
First, we define a Greeting.eigenclass method. This method returns self in the context of the eigenclass — by using the class << self ... end syntax. In this case, self contains an unnamed instance of the class Class (a.k.a an anonymous class). This anonymous class keeps track of the class to which it is attached — the Greeting class in our case.
Then, we can see that the singleton methods of the Greeting class are the instance methods of the Greeting eigenclass.
Feel free to have a look to this very detailed article to learn more about this concept.
To illustrate #Sébastien P.'s answer:
dice = [1,2,3,4,5,6] #an ordinary array instance
def dice.throw #now it has an extra
sample
end
p dice.throw #=>3

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.

Ruby mixins: extend and include

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.

Why does instance_eval() define a class method when called on a class?

Foo = Class.new
Foo.instance_eval do
def instance_bar
"instance_bar"
end
end
puts Foo.instance_bar #=> "instance_bar"
puts Foo.new.instance_bar #=> undefined method ‘instance_bar’
My understanding is that calling instance_eval on an object is supposed to allow you to define an instance variable or method for that object.
But in the example above, when you call it on class Foo to define the instance_bar method, instance_bar becomes a class method that can be invoked with "Foo.instance_bar". It is clear that this code has not created an instance method because Foo.new.instance_bar results in "undefined method ‘instance_bar’".
Why does instance_eval define a class method rather than an instance method in this context?
x.instance_eval changes your context so self evaluates to x.
This allows you to do many things, including defining instance variables and instance methods but only for x.
x = Object.new
y = Object.new
# define instance variables for x and y
x.instance_eval { #var = 1 }
y.instance_eval { #var = 2 }
# define an instance method for all Objects
class Object
def var
#var
end
end
x.var #=> 1
y.var #=> 2
Ruby lets you define instance methods for an object in a couple places. Normally,
one defines them in a class, and those instance methods are shared among all instances
of that class (like def var above).
However, we can also define an instance method for just a single object:
# here's one way to do it
def x.foo
"foo!"
end
# here's another
x.instance_eval do
# remember, in here self is x, so bar is attached to x.
def bar
"bar!"
end
end
Even though x and y have the same class, they don't share these methods, since they were only defined for x.
x.foo #=> "foo!"
x.bar #=> "bar!"
y.foo #=> raises NoMethodError
y.bar #=> raises NoMethodError
Now in ruby, everything's an object, even classes. Class methods are just instance methods
for that class object.
# we have two ways of creating a class:
class A
end
# the former is just syntatic sugar for the latter
B = Class.new
# we have do ways of defining class methods:
# the first two are the same as for any other object
def A.baz
"baz!"
end
A.instance_eval do
def frog
"frog!"
end
end
# the others are in the class context, which is slightly different
class A
def self.marco
"polo!"
end
# since A == self in here, this is the same as the last one.
def A.red_light
"green light!"
end
# unlike instance_eval, class context is special in that methods that
# aren't attached to a specific object are taken as instance methods for instances
# of the class
def example
"I'm an instance of A, not A itself"
end
end
# class_eval opens up the class context in the same way
A.class_eval do
def self.telegram
"not a land shark"
end
end
Note again, that all these methods are A-specific, B doesn't get access to any of them:
A.baz #=> "baz!"
B.telegram #=> raises NoMethodError
The important thing to take away from here is that
class methods are just instance methods of an object of class Class
The purpose of 'instance_eval' is to extend objects, but the purpose of 'class_eval' is to extend classes. And because classes are also objects, you can apply instance_eval on classes.
I guess that extending of classes is just more understandable in classic OOP. Dynamic languages allow us to easily specify behaviour of particular objects. Fact that each object can have own behaviour adds a lot of flexibility designing an application. Not only data can vary for objects of the same class. Two humans differ not only because they were born in different years, not only because they have different parents but they can think different and thus behave different.
Ability to change the behaviour of each object is fundamental. It exists in many languages.
Thinking about instance_eval think about objects first. Then you'll realize that classes are also objects - objects which additional purpose to create new objects, to hold description of common behaviour (methods). You can not only use definition of a class, but can also assign class to a variable, pass class as an argument, call method on a class, program a class!
I would recommend articles written by Yehuda Katz and Yugui to dive deeper into it:
http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/
http://yugui.jp/articles/846

Resources