views:

221

answers:

2

Multiple inheritance is great, and Perl handles it just fine as long as you have a clear understanding of your inheritance heirarchy and some of the potential pitfalls (such as those described in perldoc perltoot). Yet it does not discuss the prohibition of using the fields pragma with multiple inheritance. Indeed, I can find no documentation about this whatsoever...

Here's an illustration:

package Parent1;
use fields 'field1';

package Parent2;
use fields 'field2';

package Child;
use base qw(Parent1 Parent2);

This fails with the error: "Can't multiply inherit fields at..."

This doesn't work even when both parents have the same fields.. even when they are provably the same, because they come from a shared grandparent:

package Grandparent;
use fields qw(field1);

package Parent1;
use base 'Grandparent';

package Parent2;
use base 'Grandparent';

package Child;
use base qw(Parent1 Parent2);

One pitfall to implementing this properly is the invariant that the index of a field in a child object is always the same as the index in its parent. I'm not sure this requirement is truly needed, however... unlike in C++, where an object may be accessed using a pointer typed to a parent, Perl always knows the real type of an object when operating on its reference (indeed the fields pseudohash is essentially a vtable, kept on every single object instance). And particularly in the second example above, the fields inherited from each parent come from both parents, so they can be folded together and there is no conflicting index.

I'm sure there are other issues as well, but I haven't yet found them.

Can anyone with some knowledge of Perl's internals comment on this?

+3  A: 

1) You can try to use delegation instead of inheritance, as described here.

2) Also, some documentation (including the link above) seems to imply that the problem with the multiple inheritance is because of pseudohashes. Perl 5.10 changed the implementation of "fields" pragma to something other than pseudohashes - if it's an option, try the approach you used in Perl5.10 and it just might work (I don't have acces to 5.10 so can't experiment, sorry)

P.S. Regarding "I can find no documentation about this whatsoever..." - at least one mention of this in "official" documentation is a quote from the Camel book ("Programming Perl", O'Reilly's Perl series), 3rd Edition, chapter 31.3. "use base":

"Multiple inheritance of field classes is not supported. The use base pragma raises an exception if more than one named base class has fields."

DVK
This doesn't work in perl 5.10 either.
Chris Simmons
+3  A: 

The fields pragma was an interesting experiment, but in my opinion, a failed one. It's most useful feature, compile time checking of attribute hash keys, was removed in 5.10. There are a number of decent class composition modules on CPAN, as well as the heavyweight but steadily growing in popularity Moose ("A postmodern object system for Perl 5").

That said, if you wanted to make an effort to add multiple inheritance support, it would probably be welcomed; note that fields is now maintained independently from perl as part of the "base" distribution. You'd have to make it work with both the pseudohash based (pre-5.9.0) and restricted hash based (5.9.0+) implementations, though.

ysth