On Oct 6, 2007, at 7:48 PM, Jason Perkins wrote:

>
> On Oct 6, 2007, at 3:58 PM, James Edward Gray II wrote:
>
>> On Oct 6, 2007, at 3:55 PM, Sylvain Joyeux wrote:
>>
>>> On Saturday 06 October 2007, MenTaLguY wrote:
>>>> On Sat, 2007-10-06 at 19:17 +0900, Sylvain Joyeux wrote:
>>>>> The bottom line being: if I was to *not* use inheritance for my
>>>>> purposes, I would have to reinvent the "inheritance wheel".
>>>>
>>>> (The one sticking point I would occasionally hit was delegation, as
>>> See the top of my previous post: you're talking about duck  
>>> typing, which
>>> does not apply in my case since I *need* to manipulate the  
>>> models, and I
>>> need (for instance) to be able to check that an objet is kind_of? a
>>> particular class/module.
>>
>> Delegation does not mean duck typing.  You are confusing your  
>> terminology.
>
> [offlist]
>
> I'm enjoying this thread. Would you please consider elaborating on  
> this notion in the thread itself?

Sure, I'll try.

For the record though, the issues I'm about to discuss don't seem to  
relate to Sylvain's complaints about a lack of MI.  For that reason,  
I've renamed this subthread.

Delegation is a form of composition, like inheritance.  The design  
patterns movement has pushed that delegation is is more flexible to  
inheritance and should be preferred when we are designing objects.

It comes in many, many forms but one example might be that we want a  
strict Queue object.  We want to allow enqueueing and dequeuing items  
and peeking at the top item, but we don't want users accessing items  
in the middle of the Queue.  One way to create this is to delegate  
the needed operations to an Array:

require "forwardable"

class Queue
   def initialize
     @queue = Array.new
   end

   extend Forwardable

   def_delegators :@queue, :shift, :<<
   alias_method :enqueue, :<<
   alias_method :dequeue, :shift

   def peek
     @queue.first  # don't delegate because it allows:  first(n)
   end
end

if __FILE__ == $PROGRAM_NAME
   q = Queue.new
   %w[one two three].each { |num| q.enqueue num }
   4.times { p q.dequeue }
end

__END__

Duck typing is a concept that says we should view the type of an  
object by what it can do, more than what it is.  The deeper you go  
with this line of thought you generally come to realize than type  
checking can often be avoided and leads to more powerful code when it  
is.  For example, an add_event() method could work with an Array, our  
new Queue, or something else entirely:

$ irb -r queue
 >> def add_event(event_list)
 >>   event_list << :event
 >> end
=> nil
 >> add_event(Array.new)
=> [:event]
 >> q = Queue.new
=> #<Queue:0x14f6ce8>
 >> add_event(q)
=> [:event]
 >> q.peek
=> :event

This are simplified explanations, but hopefully the begin to  
illustrate the differences.

James Edward Gray II