Subtle Inheritance Trap

Ovid on 2009-02-01T20:27:18

Multiple Inheritance can be tricky, particularly when you get wild and crazy and have an unbalanced inheritance graph:

{
    package Platypus;
    our @ISA = qw;
    package Duck;
    our @ISA = 'SpareParts';
    sub quack {}
    package SpareParts;
    our @ISA = 'Animal';
    sub quack {}
    package Animal;
}

See the bug? It's right there, staring you in the face.

Does this help?

         Animal
           |
      SpareParts
       |    |   
       |   Duck 
       |    |   
      Platypus

As both 'SpareParts' and 'Duck' have a 'quack' method, the one in 'Duck' is unreachable if the Platypus inherits from the SpareParts first.

my $platypus = Class::Sniff->new({
    class => 'Platypus',
});
explain $platypus->unreachable;

That correctly reported Duck::quack as unreachable. I'm really quite astonished that it seems to be working.

Oh, and I've already removed an unneeded method in TAP::Parser which I detected with this.

I've now added support for listing all classes which multiply inherit and there's optional 'UNIVERSAL' support, if needed.


Another thing to sniff for...

Alias on 2009-02-02T01:18:41

While you're analysing object/inheritance trees, one case that was in my old non-CPAN equivalent tested for the following.

Class: Foo::Bar
Method: Foo->Bar

Resulting bug?

Foo::Bar->baz parses as Foo::Bar()->baz, forcing you to do Foo::Bar::->baz instead (or something like that...)