Daniel Berger wrote:
> Hi all,
> 
> I'm trying to setup an abstract base class as a factory for its
> subclasses.  The below code fails, as it always returns an instance of
> Foo::Bar instead of one of its subclasses.
> 
> module Foo
>    class Bar
>       def initialize(arg)
>          return if self.class != Foo::Bar
>          case arg.downcase
>             when 'baz'
>                return Baz.new(arg)
>             when 'zap'
>                return Zap.new(arg)
>          end
>       end
>    end
> 
>    class Baz < Bar
>    end
> 
>    class Zap < Bar
>    end
> end
> 
> fb = Foo::Bar.new('baz')
> p fb # Returns Foo::Bar, but I want Foo::Baz
> 
> Perhaps my whole approach is wrong.  What is the proper way to achieve
> what I'm after (without resorting to making Bar a module)?

I am more inclined to question your approach than not.  After all, if 
you know the class name (even if it is lowercase) you can use that 
directly to create instances - even if you do the crude "eval(foo).new" 
(using const_get is probably better anyway).

My question for you is, what are you eventually trying to achieve?  If 
you want to be able to use some kind of tag as a shortcut for the class 
to use for instance creation then using a Hash with class instances will 
be serving you well.

module Foo
   CLASSES = {}

   def self.create(tag, *args,&bl)
     CLASSES[tag].new(*args,&bl)
   end

   class Bar
     CLASSES["baz"] = self
   end
end

Foo.create "baz"

Whether you need that create method and the module at all is probably a 
different question.

Kind regards

	robert