On 12/3/06, Robert D. [email protected] wrote:
Which would follow from one of the basic rules of OOP, if memory serves:
A Class does not know anything about its subclasses, be it abstract or not.
OP I suggest that you rethink your design, AFAIK that would not be very
flexible concerning new subclasses right?
Of course every rule has exceptions. For example, in Beck’s
Test-Driven Development, after a bit of refactoring you end up with
something like (converted to Ruby
class Money
class << self
def dollar(amount)
Dollar.new amount
end
def franc(amount)
Franc.new amount
end
end
end
The reasoning behind this is that since the clients only go through
Money, you can change the underlying inheritance structure without
breaking anything. Indeed, he goes on to get rid of the Dollar and
Franc classes entirely, and the factory methods turn into:
def dollar(amount)
new amount, “USD”
end
In the case of the Money class, client code shouldn’t have a
dependency on Dollar or Franc classes. Adding a factory method onto
the Money class simplifies client code and promotes refactoring.
It’s impossible to tell if OP’s situation would be a good use for this
kind of thing, given the lack of explanation and the nondescriptive
names
I would prefer to have explicit factory methods though, instead of a
single new method that can return an instance of any number of
classes. As far as it not being flexible with subclasses, a little
bit of metaprogramming clears that up:
class Bar
def self.factory_methods(*names)
names.each do |n|
(class << self; self; end).instance_eval do
define_method(n) {
Kernel.const_get(n.to_s.capitalize).send(:new) }
end
end
end
end
class Bar
factory_methods :baz, :zap
end
Gives you Bar.baz and Bar.zap which return a new Baz and Zap instance,
respectively.
Hell you could even use the inherited callback to do it automatically:
class Bar
def self.inherited(subclass)
(class << self; self; end).instance_eval do
define_method(subclass.to_s.downcase) { subclass.new }
end
end
end
Then when you do
class Baz < Bar; end
you automatically get Bar.baz
I’ll be honest, I really just saw this whole thing as an opportunity
to do some fun meta-foo Use at your own risk.
Pat