Best way to inject new functionality into a class


#1

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


#2

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