Subject: | YAML::Marshall does strange things to the @ISA inheritance chain |
Hi,
I've been trying to use YAML::Marshall to invoke the constructor of
classes named with tags in the YAML file. Possibly I've misundersto\
od something, particularly I don't understand the syntax 'use
YAML::Marshall -mixin;' mentioned in the YAML::Marshall manual.
YAML::Marshall's import routine pushes the class name of the module
being used onto the @ISA base-class list of the package using it. \
Usually this has the desired effect of making modules using
YAML::Marshall or it's derivatives mix-in the methods it provides with
their\
own.
However, in the following case, it creates spurious inheritance chains.
A toy example. We want to have person nodes, and these can have
addresses, like this.
---
person: !person
name: Joe
address: !address
street: 1 skid row
town: hicksville
These are put in files Person.pm, and Address.pm:
package Person;
use base 'YAML::Marshall';
sub new { bless { type => 'person' }, shift; }
1;
package Address;
use base 'YAML::Marshall';
sub new { bless { type => 'address' }, shift; }
1;
I'm not worrying about registering tags for these classes, because
that doesn't affect the problem I'm trying illustrate:
$ perl -de 0
Loading DB routines from perl5db.pl version 1.28
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(-e:1): 0
DB<1> use Person;
DB<2> x @Person::ISA
0 'YAML::Marshall'
1 'Address'
DB<3>
Surprise! A Person is-a Address! This is purely because we've used the
Address module.
To work around this, you need to 'use Address();' in Person.pm. But
this isn't always easy to figure out: YAML::Marshall::import does the
deed, and if you don't realise it's responsible for the magic it can be
quite perplexng when your classes don't behave as you expect. When the
importing package has other base classes, this can go unnoticed; when it
doesn't, it is likely to be more catastrophic: the class gets
YAML::Marshall or a subclass as a base, and its behaviour can change
radically.
YAML::Marshall's import() function seems to implement the rule "if the
use'ing package isn't a subclass of the imported package, make it
one". Do we really need to be a subclass of it when we haven't
explicitly mixed it in as a base?