From: "Ara.T.Howard" Date: 2005-08-20T00:20:16+09:00 Subject: Re: Controlling acces to object instantiation? On Sat, 20 Aug 2005, Andrew S. Townley wrote: > Hello everyone, > > Trying to get my head around some of the subtleties of Ruby. I've done > quite a bit of C/C++/Java and some Python programming, and the normal > way that I'd solve this problem (in pseudo-Java) would be: > > interface SomeFeature > { > void execute(); > } > > public class FeatureFactory > { > private static class FeatureImpl implements SomeFeature > { > public FeatureImpl(String initParam1, > String initParam2) > { > ... > } > > public void execute() { ... } > } > > public SomeFeature createFeature() > { > return new FeatureImpl("param1", "param2"); > } > } > > I've seen some of the previous threads on the list (starting from here: > http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/60616), but > I don't see anything immediately obvious as to how to encapsulate the > creation of my concrete implementations of a common interface (even with > duck typing, there's an implied interface). > > The main issue here is that I want to prevent the client code from > instantiating their own objects. The objects should be created only by > a factory of some sort (who has implementation-specific configuration > information about how to bootstrap them). > > It would appear that if you have 'require'd the appropriate files (or > can), you can create any instances you want. Is there a way to > accomplish what I'm trying to do beyond saying "don't do that" in the > documentation? > > Any assistance would be appreciated. > > Thanks in advance, harp:~ > cat a.rb module Factory @classes = { 'a' => ( Class::new do class << self def foo; 42; end end def bar; 42.0; end end ), 'b' => ( Class::new do class << self def foo; 'FORTY-TWO'; end end def bar; 'forty-two'; end end ), } def self::new(*a, &b) class_for(a.shift)::new(*a, &b) end def self::class_for typename @classes[typename] end end a_obj = Factory::new 'a' b_obj = Factory::new 'b' a_class = Factory::class_for 'a' b_class = Factory::class_for 'b' p a_obj.bar p b_obj.bar p a_class::foo p b_class::foo harp:~ > ruby a.rb 42.0 "forty-two" 42 "FORTY-TWO" obviously you would want 'class_for' to be private - but this illustrates the general idea. hth. -a -- =============================================================================== | email :: ara [dot] t [dot] howard [at] noaa [dot] gov | phone :: 303.497.6469 | Your life dwells amoung the causes of death | Like a lamp standing in a strong breeze. --Nagarjuna ===============================================================================