On Wednesday 23 February 2005 09:58 pm, Sam Roberts wrote:
> > You could do ...
> >
> >   class A
> >     def do_something() ... end
> >   end
> >   class B
> >     def do_something() ... end
> >   end
> >
> >   t.do_something
>
> I know where you are coming from, this is a nice pattern, but in this
> case t is a return value of Resolv::DNS::Message#question, and I have to
> answer the question. How I answer the question depends on the question
> (of course!), but is not part of the behaviour of the question,
> different "answers" answer the question in different ways.

I'm not sure if you are saying that won't work because (1) the do_something 
method is not part of the behavior of the classes in question, or (2) you 
need to respond differently to these classes in different circumstances.  Or 
perhaps both (1) and (2) are the case.

If (1), then remember that you can always open up any class and add more 
behavior.  

If (2), then you can do something like the following (simple visitor pattern):

  module Kernel
    def accept_visitor(visitor)
      visitor.send("visit_" + self.class.name.downcase.gsub(/::/, '_'), self)
    end
  end
  
  class A; end  
  class B; end
  
  class MySpecialVisitor
    def visit_a(a)
      puts "Doing something with A: (#{a})"
    end
    def visit_b(b)
      puts "Doing something else with B: (#{b})"
    end
  end
  
  A.new.accept_visitor(MySpecialVisitor.new)
  B.new.accept_visitor(MySpecialVisitor.new)

You can define as many visitors as you need to get the varied behaviors 
required by your problem.

The solution is a bit more complicated, but allows open-ended behaviors for 
any class.

-- 
-- Jim Weirich    jim / weirichhouse.org     http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct, 
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)