Forum: Ruby best way to inject new functionality into a class

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Chuck R. (Guest)
on 2008-10-07 23:24
(Received via mailing list)
I've pretty much made up my mind how to modify my classes, but I
thought I would throw this issue out to the community at large to see
if I'm missing something glaringly obvious.

When I write code for classes & modules that need to collaborate, I
typically inject the functionality of one into the other one of two
ways (I rarely subclass). My code will explain.

#1

module Foo
   def baz; # do something;   end
end

class Bar
   include Foo # Bar takes on Foo's methods
end


#2

class Foo
   def baz; # do something;   end
end

class Bar
   attr_accessor :strategy  # implement the strategy pattern
end

bar = Bar.new
bar.strategy = Foo.new


Recent projects at work are forcing me to be a little more dynamic
than #1 can be, and #2 can be error-prone since there is a lot more
setup & wire code required.

As I continue to explore the ruby language, I ran across another
mechanism for class modification.

#3

module Foo
   def baz; # do something;   end
end

class Bar
end

bar = Bar.new
bar.extend(Foo)


This third way looks like the cleanest way of all. It has the added
benefit that "later" during runtime I could change my mind and replace
the Foo module with another one that implements the same methods.

bar.extend(Baz) # overrides all methods with the same signature as Bar
or Foo


Do you, in general, agree that using #extend is at least superior to #2?

Thanks for any insights and feedback.

cr
David A. Black (Guest)
on 2008-10-07 23:31
(Received via mailing list)
Hi --

On Wed, 8 Oct 2008, Chuck R. wrote:

> module Foo
> class Foo
>
> def baz; # do something;   end
> that "later" during runtime I could change my mind and replace the Foo module
> with another one that implements the same methods.
>
> bar.extend(Baz) # overrides all methods with the same signature as Bar or Foo
>
>
> Do you, in general, agree that using #extend is at least superior to #2?

I think they all have their uses, but I'll mention that #extend has
always been my favorite choice for modifying core functionality:

   module DifferentArray
     ...
   end

   a = [].extend(DifferentArray)

etc. If you're writing your own classes then including a module in a
class is quite legit and powerful.


David
This topic is locked and can not be replied to.