Hi list,
I am reading the book ‘design patterns in ruby’. On page 201 I find
this code example:
require ‘forwardable’
class WriterDecorator
extend Forwardable
def_delegators :@real_writer, :write_line, :rewind, :pos, :close
def initialize (real_writer)
@real_writer = real_writer
end
end
I am a bit surprised by the ‘extend Forwardable’ line. Can anybody
explain me what this is? Is it the same as ‘include Forwardable’ or is
it the same as ‘class WriterDecorator < Forwardable’?
thanks in advance, Ruud
I am a bit surprised by the ‘extend Forwardable’ line. Can anybody
explain me what this is? Is it the same as ‘include Forwardable’ or is
it the same as ‘class WriterDecorator < Forwardable’?
It’s neither. extend() is method that all objects have (classes are
objects
too). It takes the methods from a module (in this case Forwardable) and
adds
them as singleton methods to the object. Forwardable contains the method
‘def_delegators’, which we see here has been added as a singleton method
to
WriterDecorator.
ruud grosmann wrote:
I am a bit surprised by the ‘extend Forwardable’ line. Can anybody
explain me what this is? Is it the same as ‘include Forwardable’ or is
it the same as ‘class WriterDecorator < Forwardable’?
No, it’s the same as WriterDecorator.extend Forwardable or
class <<WriterDecorator
include Forwardable
end
I.e. the module gets included in the singelton class of WriterDecorator,
not
in WriterDecorator itself (or in other words: the module’s methods get
added
as singleton methods of the class instead of as instance methods)
Hi –
On Tue, 30 Sep 2008, ruud grosmann wrote:
def_delegators :@real_writer, :write_line, :rewind, :pos, :close
def initialize (real_writer)
@real_writer = real_writer
end
end
I am a bit surprised by the ‘extend Forwardable’ line. Can anybody
explain me what this is? Is it the same as ‘include Forwardable’ or is
it the same as ‘class WriterDecorator < Forwardable’?
It’s like a per-object include operation.
module M
def speak
puts “Hi!”
end
end
obj = Object.new
obj.extend(M)
obj.speak # “Hi!”
The example you’ve got extends the class object WriterDecorator. It’s
like this:
class C
extend M
end
C.speak # “Hi!”
David
Hi –
On Tue, 30 Sep 2008, ruud grosmann wrote:
class, not an object?
As such, Forwardable is mixed in, is my first thought. What have I
understood wrongly?
Classes are objects.
c = Class.new # c is an object whose class is Class
c.extend(SomeModule)
Every class is an instance of the class Class, so you can extend
classes just like other objects.
I’ve always said that the answer to 75% of all questions about Ruby
is: Classes are objects It’s definitely a very key thing.
David
It’s neither. extend() is method that all objects have (classes are objects
too). It takes the methods from a module (in this case Forwardable) and adds
them as singleton methods to the object. Forwardable contains the method
‘def_delegators’, which we see here has been added as a singleton method to
WriterDecorator.
thank you for your replies. But I’m afraid that I need some more
explanation. Isn’t a singleton method a method that applies to the
singleton class of one object? And in this case we’re talking about a
class, not an object?
As such, Forwardable is mixed in, is my first thought. What have I
understood wrongly?
regards, RUud
ruud grosmann wrote:
Isn’t a singleton method a method that applies to the
singleton class of one object?
It is a method that is defined on the singleton class of an object, yes.
As a singleton class by definition only has one instance that means that
a
singleton method is a method that can be called on a single object and
that
object only.
And in this case we’re talking about a
class, not an object?
A class is an object:
String.is_a? Class
=> true
String.is_a? Object
=> true
String.object_id
=> -605959678
As such, Forwardable is mixed in, is my first thought.
It is mixed in. It’s mixed into WriterDecorator’s singleton class.
What have I understood wrongly?
I’m not sure. Maybe you mistakenly assumed that a class is its own
singleton
class?
HTH,
Sebastian
Hi –
On Tue, 30 Sep 2008, Sebastian H. wrote:
ruud grosmann wrote:
Isn’t a singleton method a method that applies to the
singleton class of one object?
It is a method that is defined on the singleton class of an object, yes.
As a singleton class by definition only has one instance that means that a
singleton method is a method that can be called on a single object and that
object only.
Although:
class C
end
class D < C
end
def C.x
end
D.x # subclass can call superclass’s singleton methods
Technically, it’s also true that if you extend an object with a
module, you’re not really writing singleton methods, since the methods
in the module are available to other objects that use the module. The
singleton_method_added callback won’t get called, for example.
David
David
Am a little confused by your codes, from all I understood in these
threads.
module M
def speak
puts “Hi!”
end
end
obj = Object.new
obj.extend(M)
obj.speak
obj.speak should be Object.speak. Why is yours different? And your
second code agreed with singleton idiom.
Janus
Hi –
On Tue, 30 Sep 2008, ruud grosmann wrote:
Please correct me if I’m wrong.
The only thing I’d add is that it’s not really accurate to describe
methods defined in a module as “singleton methods” of an object that
extends itself with the module. A singleton method is really a method
defined in the object’s singleton class itself.
David
OK. I think now I get what you mean.
To make sure I understood it right:
my mistake was that there are both singleton methods on classes and
singleton methods on instances of a class. Essentially the same,
because classes are objects too. In this case, we’re talking about
singleton methods on the class WriterDecorator. This is done because
the Forwardable method ‘def_delegators’ is used by the class object
only, not by it’s instances. Which would have been the case if
Forwardable was mixed in.
Please correct me if I’m wrong.
Thanks anyway for the time spent on helping me on this!
regards, Ruud
David,
Oh! It is clear now to me.
Janus
Hi –
On Tue, 30 Sep 2008, janus wrote:
obj = Object.new
obj.extend(M)
obj.speak
obj.speak should be Object.speak. Why is yours different? And your
second code agreed with singleton idiom.
I’m not sure what you mean by “should be”. The way it’s written,
Object does not have a “speak” method, but obj does. That’s the effect
of extend: it adds module-based functionality to a single object.
David