From: Raul Parolari Date: 2007-11-19T13:25:23+09:00 Subject: Re: Composition: Build objects from other objects Thufir wrote: > On Sun, 18 Nov 2007 06:20:04 +0900, Raul Parolari wrote: > >> 1) Thufir was right .. > Well that's very complimentary of you :) Just stating a fact in the summary I attempted to do (which does not include the interesting and alternative view given by Trans, which came after). > I need to learn more about Delegation.. You can learn what Delegation is very easily; the real work in the Forwarding module is done in a few lines; I wrote a mini-version of the module removing exception processing and others things not necessary, to play with it a bit. Look at this simplified version (used in the example below): module Simple_Forwardable def def_delegator(accessor, method, ali = method) module_eval(<<-EOS) def #{ali}(*args, &block) #{accessor}.send(:#{method}, *args, &block) EOS end end Believe it or not, these 6 lines are the heart of Forwardable; in short, in case you are not familiar with some things: a) the method 'send' is used to 'send' a method name (eg, a method that you have in a string or symbol, for example that you collected from a web form or cmd line) to an object. b) the module_eval allows to define dynamically methods using interpolation. That's it! If the syntax looks a bit mysterious at first, look at 'accessor' as our @engine object and 'method' as 'vroom'. Notice that we can even name an alias for 'vroom' if in the Vehicle class we prefer a different name (say, 'rev'); and,we can even pass arguments (eg, we can pass the level of the vroom we want). Both are done in the file below. Below is the file that you may want to play with, if you find it useful (it combines the 2 examples given by Liam in one file; perhaps there are too many options, but you will decide that). Good luck! and perhaps let us know how your project goes and if stood up well to the shock with 'reality' :-) Raul module Simple_Forwardable def def_delegator(accessor, method, ali= method) module_eval(<<-EOS) def #{ali}(*args, &block) #{accessor}.__send__(:#{method}, *args, &block) end EOS end end # from Liam's examples, combined class Engine def vroom(level) puts "vroom #{level}" end end class MustangEngine def vroom(level) puts "rumble #{level}" end end class Vehicle extend Simple_Forwardable def_delegator :@engine, :vroom, :rev attr_accessor :engine def initialize(engine) @engine=engine end end class Factory def self.build_car Vehicle.new(Engine.new) end end falcon = Factory.build_car falcon.rev('mid') # => vroom mid v = Vehicle.new(Engine.new) v.rev('high') # => vroom high # changing the engine v.engine = MustangEngine.new v.rev('low') # => rumble low -- Posted via http://www.ruby-forum.com/.