The way it works is actually pretty simple: just put more than one package
name in your @ISA
array. When it comes time for Perl to go
finding methods for your object, it looks at each of these packages in
order. Well, kinda. It's actually a fully recursive, depth-first order.
Consider a bunch of @ISA
arrays like this:
@First::ISA = qw( Alpha ); @Second::ISA = qw( Beta ); @Third::ISA = qw( First Second );
If you have an object of class Third:
my $ob = Third->new(); $ob->spin();
How do we find a spin
method (or a new
method for
that matter)? Because the search is depth-first, classes will be looked up
in the following order: Third, First, Alpha, Second, and Beta.
In practice, few class modules have been seen that actually make use of MI. One nearly always chooses simple containership of one class within another over MI. That's why our Person object contained a Fullname object. That doesn't mean it was one.
However, there is one particular area where MI in Perl is rampant: borrowing another class's class methods. This is rather common, especially with some bundled ``objectless'' classes, like Exporter, DynaLoader, AutoLoader, and SelfLoader. These classes do not provide constructors; they exist only so you may inherit their class methods. (It's not entirely clear why inheritance was done here rather than traditional module importation.)
For example, here is the POSIX module's @ISA:
package POSIX; @ISA = qw(Exporter DynaLoader);
The POSIX module isn't really an object module, but then, neither are Exporter or DynaLoader. They're just lending their classes' behaviours to POSIX.
Why don't people use
MI for object methods much? One reason is that it can have complicated side-effects. For one thing, your inheritance graph (no longer a tree) might converge back to the same base class. Although Perl guards against recursive inheritance, merely having parents who are related to each other via a common ancestor, incestuous though it sounds, is not forbidden. What if in our Third class shown above we wanted its new
method to also call both overridden constructors in its two parent classes? The
SUPER notation would only find the first one. Also, what about if the Alpha and Beta classes both had a common ancestor, like Nought? If you kept climbing up the inheritance tree calling overridden methods, you'd end up calling Nought::new() twice, which might well be a bad idea.