Extend keyword in class definition

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)

···

--
Jabber: sepp2k@jabber.org
ICQ: 205544826

Hi --

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'?

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

···

On Tue, 30 Sep 2008, ruud grosmann wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
   Advancing with Rails January 19-22 Fort Lauderdale, FL *
   * Co-taught with Patrick Ewing!
See http://www.rubypal.com for details and updates!

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

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 --

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?

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 :slight_smile: It's definitely a very key thing.

David

···

On Tue, 30 Sep 2008, ruud grosmann wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
   Advancing with Rails January 19-22 Fort Lauderdale, FL *
   * Co-taught with Patrick Ewing!
See http://www.rubypal.com for details and updates!

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

···

--
NP: Depeche Mode - Lilian
Jabber: sepp2k@jabber.org
ICQ: 205544826

Hi --

···

On Tue, 30 Sep 2008, janus wrote:

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.

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

--
Rails training from David A. Black and Ruby Power and Light:
   Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
   Advancing with Rails January 19-22 Fort Lauderdale, FL *
   * Co-taught with Patrick Ewing!
See http://www.rubypal.com for details and updates!

Hi --

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

···

On Tue, 30 Sep 2008, Sebastian Hungerecker wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
   Advancing with Rails January 19-22 Fort Lauderdale, FL *
   * Co-taught with Patrick Ewing!
See http://www.rubypal.com for details and updates!

David,

Oh! It is clear now to me.

Janus

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

···

On 30/09/2008, David A. Black <dblack@rubypal.com> wrote:

Hi --

On Tue, 30 Sep 2008, Sebastian Hungerecker 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

--
Rails training from David A. Black and Ruby Power and Light:
   Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
   Advancing with Rails January 19-22 Fort Lauderdale, FL *
   * Co-taught with Patrick Ewing!
See http://www.rubypal.com for details and updates!

Hi --

···

On Tue, 30 Sep 2008, ruud grosmann wrote:

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.

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

--
Rails training from David A. Black and Ruby Power and Light:
   Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
   Advancing with Rails January 19-22 Fort Lauderdale, FL *
   * Co-taught with Patrick Ewing!
See http://www.rubypal.com for details and updates!