[Q] best way to inject new functionality into a class

C

Chuck Remes

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
 
D

David A. Black

Hi --

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?

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

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

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top