From: Vladimir Agafonkin Date: 2006-01-25T03:08:12+09:00 Subject: Re: The Duck Problem, or accessing one instance var from another Thanks, Robert. You're right, a strategy pattern (I just started reading "Head First Design Patterns" of O'Reilly). What do you mean by manually keep references synchronized? I implented my solution with cross-references, and it seems quite automated (though there's still room for improvement). Here's what I came with (in short): #================================================ class Duck attr_reader :name def initialize(name, fly_behaviour=:fly_with_wings, quack_behaviour=:quack) @fly_behaviour = FlyBehaviour.new(self, fly_behaviour) @quack_behaviour = QuackBehaviour.new(self, quack_behaviour) @name = name end def fly @fly_behaviour.perform end def quack @quack_behaviour.perform end end class Behaviour def initialize(object, behaviour); @obj = object; @behaviour = behaviour; end def perform send(@behaviour) end def self.list; self.protected_instance_methods end end class FlyBehaviour < Behaviour protected def fly_with_wings puts "#{@obj.name} is flying!" end def do_not_fly puts "#{@obj.name} can't fly. :-(" end end class QuackBehaviour < Behaviour protected def quack puts "#{@obj.name} is quacking! Quack!!" end def squeak puts "#{@obj.name} is quacking! Squeak!!!" end end class RubberDuck < Duck def initialize(name) super(name,:do_not_fly,:squeak) end end ducks = [] ducks << Duck.new("George") ducks << RubberDuck.new("Wacky") ducks.each do |duck| duck.quack duck.fly end p QuackBehaviour.list #================================================ The next big thing would be to implement generating behaviour-related methods in the Duck class on the fly. Through method_missing, maybe? And, of course, behaviour instance variables too. That seems a bit harder to do, but I'm a programming newbie after all! :-) The perfect use of the solution would look like: usually_able_to :fly, :quack, :swim that looks similiar to Rails has_many and belongs_too. Maybe I need to check it's code for an idea. And there's another question: how to make all methods defined in Behaviour children protected? The code would be more attractive if I hadn't to write "protected" in the beginning of each behaviour child.