include vs. extend

Discussion in 'Ruby' started by Daniel DeLorme, Jul 11, 2006.

  1. I was under the impression that include and extend were basically module-level
    and object-level versions of the same thing, that including a module at the
    class level had the same effect as extending an object. But it seems there is a
    big difference:

    class Foo
    include Enumerable
    end
    class Bar
    def initialize
    extend Enumerable
    end
    end
    (class << Foo.new;self;end).ancestors #=> [Foo, Enumerable, Object, Kernel]
    (class << Bar.new;self;end).ancestors #=> [Enumerable, Bar, Object, Kernel]

    This makes a whole world of difference when you want to wrap certain methods
    with additional functionality. In such cases you *have* to use extend (or ugly
    techniques like aliasing the old method). Why the difference? In what cases
    should I use include and what cases should I use extend?

    Daniel
    Daniel DeLorme, Jul 11, 2006
    #1
    1. Advertising

  2. Daniel DeLorme

    Guest

    Hi --

    On Tue, 11 Jul 2006, Daniel DeLorme wrote:

    > I was under the impression that include and extend were basically
    > module-level and object-level versions of the same thing, that including a
    > module at the class level had the same effect as extending an object. But it
    > seems there is a big difference:
    >
    > class Foo
    > include Enumerable
    > end
    > class Bar
    > def initialize
    > extend Enumerable
    > end
    > end
    > (class << Foo.new;self;end).ancestors #=> [Foo, Enumerable, Object, Kernel]
    > (class << Bar.new;self;end).ancestors #=> [Enumerable, Bar, Object, Kernel]
    >
    > This makes a whole world of difference when you want to wrap certain methods
    > with additional functionality. In such cases you *have* to use extend (or
    > ugly techniques like aliasing the old method). Why the difference? In what
    > cases should I use include and what cases should I use extend?


    It's understood that if you extend an object, it's because you *want*
    to put the module ahead of the object's class in the method look-up
    path. Otherwise, you'd put the functionality you want in the class
    :) By the same token, it would be very unusual to put extend in
    initialize.

    Basically you use extend when you want to control behavior via modules
    on a per-object basis. A common use is for classes:

    module M
    def meth
    puts "Hi"
    end
    end

    class C
    extend M
    end

    C.meth # Hi

    obj.extend(Mod) is equivalent to:

    class << obj
    include Mod
    end

    (or very nearly equivalent; there may be some arcane difference I'm
    not remembering). So it's all really include operations -- but, when
    done with extend, the class doing the including is a singleton class.


    David

    --
    http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
    http://www.manning.com/black => RUBY FOR RAILS, the Ruby book for
    Rails developers
    http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
    => me
    , Jul 11, 2006
    #2
    1. Advertising

  3. Daniel DeLorme

    Kent Sibilev Guest

    In the first case, the proxy that refers to the Enumerable module is
    inserted between Foo class and Object class. In the second case, an
    instance of a Bar class during initialization receives a new class
    which is the same proxy object and this proxy's superclass is Bar
    class. BTW, check out this book at http://rhg.rubyforge.org. It has a
    very nice chapter about internal structure of Ruby object model.

    Kent.

    On 7/10/06, Daniel DeLorme <> wrote:
    > I was under the impression that include and extend were basically module-level
    > and object-level versions of the same thing, that including a module at the
    > class level had the same effect as extending an object. But it seems there is a
    > big difference:
    >
    > class Foo
    > include Enumerable
    > end
    > class Bar
    > def initialize
    > extend Enumerable
    > end
    > end
    > (class << Foo.new;self;end).ancestors #=> [Foo, Enumerable, Object, Kernel]
    > (class << Bar.new;self;end).ancestors #=> [Enumerable, Bar, Object, Kernel]
    >
    > This makes a whole world of difference when you want to wrap certain methods
    > with additional functionality. In such cases you *have* to use extend (or ugly
    > techniques like aliasing the old method). Why the difference? In what cases
    > should I use include and what cases should I use extend?
    >
    > Daniel
    >
    >



    --
    Kent
    ---
    http://www.datanoise.com
    Kent Sibilev, Jul 11, 2006
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?Um9iIEtheQ==?=

    Extend the Membership Provider to include more user data

    =?Utf-8?B?Um9iIEtheQ==?=, Jan 5, 2006, in forum: ASP .Net
    Replies:
    5
    Views:
    7,970
    Scott Allen
    Jan 6, 2006
  2. Andreas Bogenberger
    Replies:
    3
    Views:
    888
    Andreas Bogenberger
    Feb 22, 2008
  3. aspineux
    Replies:
    3
    Views:
    204
    aspineux
    Aug 18, 2011
  4. Gavin Kistner
    Replies:
    5
    Views:
    134
    Robert Klemme
    Oct 23, 2004
  5. Daniel Berger
    Replies:
    3
    Views:
    107
    Daniel Berger
    Oct 30, 2004
Loading...

Share This Page