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