in reply to Constructor/Factory Orthodoxy
My original question really concerned a concept of "inheritable default properties", but I mangaged to bungle my question. Obviously attribute methods, or mutators, are not the problem here with inheritance -- it's how to cascade defaults from the base class, possibly overriding with new defaults in the subclasses, etc. A related problem, but not quite the same thing. None of the answers above really addressed this, so I flipped through TheDamian's Object Oriented Perl book, learning about some of the constructor/factory issues that are addressed above. (more on that in a bit).
While doing so, the book refreshed my memory on Tie::SecureHash, which is specifically designed to handle these kinds of issues (and many more) with Perl objects. It's not perfect, but it's great for debugging and tracking problems with attributes and defaults -- then you can load it in 'fast' mode and have it drop back into behaving like a normal hash without the additional overhead. Worth reading up on if you're curious.
Also interesting were the notions of using a Registry to let the base class (perhaps via a Factory class) to wrangle with configuring the subclasses, rather than encoding knowledge of subclasses within your base class -- as dws suggested.
As for constructor/factory/cloner -- I was puzzled above by dragonchild's presumption that if new() could also be an object method, rather than a class method, that there was an expectation of it being a cloning method. I had never had this impression and thought he was making a ridiculous assumption. As it turns out, his is more likely to be the traditional assumption in Perldom, rather than mine. I had always assumed that the object version of new() behaved identically to the class method -- that is to say, Foo->new() behaves identically to $foo->new(). For me, $foo->new() was just a convenient way to avoid having to type (ref $foo)->new. Cloning was a completely separate issue, and typically a separate method, for me. So I wondered where dragonchild would get such an assumption.
Well here's an excerpt on precisely this subject, from TheDamian himself in his book:
Laziness is a cardinal virtue in Perl, so a custom has developed that when users of a class call a class's constructor as an object method, the defaults the constructor uses are taken from the original object.
(p. 103)
and later...
While many experts view the overloading of constructors as object copiers to be a natural extension of their functionality, others consider the technique unintuitive, too subtle, and more likely to produce obscure and hard-to-maintain code. Whether or not that's the case, it certainly is true that the code for the constructors themselves is considerably more complicated.
The alternative is to provide a completely separate method for duplicating objects.
(p. 105)
So there you have that -- I was certainly mistaken in my notion that there was no such expectation with $foo->new() (and I've been around Perl long enough to have no excuse). Having said that, I'd say I'm firmly in the $foo->clone() camp for copying objects.
This issue of cloning doesn't really address the differences between a constructor method and a factory method (or class). Some might argue that a constructor is just a special case of a factory. I'd always maintained a "self vs other" outlook on constructors vs factories, but that's certainly not the whole picture. Feel free to read up on them around the web yourself.
Cheers,
Matt
|
|---|