James Edward Gray II wrote:
> On Dec 3, 2006, at 12:04 AM, Joel VanderWerf wrote:
> 
>> James Edward Gray II wrote:
>>> On Dec 2, 2006, at 7:27 PM, Joel VanderWerf wrote:
>>>> module Foo
>>>>    class Bar
>>>>       def self.new(arg)
>>>>          return super() if self != Foo::Bar
>>> I don't believe that line does what you intend.  Try using your code 
>>> with something like:
>>> fb = Foo::Baz.new('baz') # => #<Foo::Baz:0x1e2ea0>
>>
>> It's a little funny to say "baz" twice, is your point?
> 
> No.  My point was that the original code forces the call to be made on 
> Foo::bar by returning nil otherwise.  Your code created the object.

Ah, I see. You are interpreting this line in the original code:

module Foo
    class Bar
       def initialize(arg)
          return if self.class != Foo::Bar   # <--- here

as a way of preventing direct instantiation of subclasses (it doesn't 
actually do that, but maybe that's what was intended). If that was the 
OP's intent, then I suggest adding protected declarations to what I 
posted before--see below.

The line

          return super() if self != Foo::Bar

is necessary so that when Bar.new sees the "baz" case and calls Baz.new, 
which is implemented not in Baz but back up in Bar, the call can be 
handled by Object.new, which will create a Baz instance and call 
#initialize on it.

Does that make sense?

Here's the modified code:

   module Foo
      class Bar
         def self.new(arg)
            return super() if self != Foo::Bar
            case arg.downcase
               when 'baz'
                  return Baz.new(arg)
               when 'zap'
                  return Zap.new(arg)
            end
         end
      end

      class Baz < Bar
         class << self; protected :new; end
      end

      class Zap < Bar
         class << self; protected :new; end
      end
   end

   fb = Foo::Bar.new('baz')
   p fb # ==> #<Foo::Baz:0xb7d66c3c>

   Foo::Baz.new("baz")  # fails

-- 
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407