Inheritance v passing object through the constructor

box ||= Box.new

class ErrorBox
  def initialize(box)

  end

end

That won't do anything as written; the two 'box' local variables are distinct.

I'm guessing you mean something like this:

class ErrorBox
   def initialize(box)
     @box = box
   end
   def draw
     @box.draw
   end
end

eb = ErrorBox.new(Box.new)
eb.draw

This is a simple example of the "delegator pattern": (an instance of) ErrorBox "has a" Box.

Over time I've found myself drawn more and more towards this pattern, and use class inheritance less and less.

For me, the biggest advantage is that you can implement composite behaviour easily. That is, your ErrorBox can contain multiple objects, either creating them itself or having them passed in. Its own method 'x' can in turn call A#y and B#z as appropriate. Composing systems in this way can make it much clearer what each piece is responsible for.

It allows cleaner decoupling: for example, the 'foo' method of Box may not make any sense when inside an ErrorBox, so you don't delegate it.

Unit testing with mock objects is easy. Your ErrorBox object can have a mock Box, and you can easily check that it calls the correct methods on Box. With inheritance you'd end up stubbing or mocking methods on the same object, which can get messy. Tests are also more robust because they don't depend on implementation details of Box.

Finally, there's more potential for code re-use. One ErrorBox object may contain a TclBox, whilst another ErrorBox object may contain a QtBox. As long as they have the same duck-type (e.g. in the above example they both respond usefully to "draw") then they'll both work, without code changes, whereas an ErrorBox which inherits from TclBox will only work with that. The decision as to which to use can even be left until runtime.

Does that answer your question?

Regards,

Brian.

If ErrorBox really is a more specialized kind of Box, then subclassing makes
sense in terms of design. If it's not really a new kind of Box but wants to
use some of Box's behaviour then use delegation or consider mixins. Reg
Braithewaite has a decent article on this topic:

http://weblog.raganwald.com/2008/04/is-strictly-equivalent-to.html

Also, seek out the decorator in a book on design patterns. It's usually
presented as a way of extending the behaviour of objects in many orthogonal
ways in situations where subclassing would result in combinatorial
explosions of new subclasses. This is another case where mixins can also
make sense.

···

2008/7/7 <b.candler@pobox.com>:

box ||= Box.new

class ErrorBox
def initialize(box)
end
end

That won't do anything as written; the two 'box' local variables are
distinct.
I'm guessing you mean something like this:
class ErrorBox
def initialize(box)
   @box = box
end
def draw
   @box.draw
end
end
eb = ErrorBox.new(Box.new)
eb.draw