Hello fellow monks,

I've got a situation where I sometimes want my class to inherit from Class A, and somtimes from Class B, depending on user request.

Let's say, for example, that my class is a type of StoneGatherer class and that most of the time I just want to gather Blue stones. Every now and then, however, I want to gather Red stones. There is no real difference between how the stones are gathered, just in what type of stones are returned.

I do indeed have to inherit from a Gatherer class of some sort -- has_a won't cut it. (and for the curious here, the two Gatherer classes in question are HTML::Parser and HTML::TreeBuilder (which itself isa HTML::Parser)).

Obviously I could make two classes, StoneGatherer::Blue and StoneGatherer::Red, which inherit from Gatherer::Blue and Gatherer::Red, respectively. But given that there's no difference in the gathering process, only what is gathered, it seems sort of silly.

What I'd like to do is abuse Exporter, overriding import() in such a way that I can just do this:

# normal mode, @ISA = qw(Gatherer::Blue) use StoneGatherer;
vs this
# red mode, @ISA = qw(Gatherer::Red) use StoneGatherer qw(red);

Now, it also occurs to me that I'm thinking about the problem completely wrong -- as I'm sure all the OO purists out there are probably screaming right now. For example, this might be a case where a 'mixin' solution is preferred.

I'd like to know a) if it is wrong, how wrong is it, b) what's the 'right' way to think about the problem, and c) if there are multiple solutions, what are they?

Thanks for your time and thoughts,
Matt

P.S. As an aside, there are examples of abusing Exporter out there, such as with Test::More:

use Test::More tests => 42;

Any other examples out there? ;)

Update: in tracking down references, I came across the following illustration in the PerlDesignPatterns wiki regarding the AbstractClass pattern:

Explicitly using, then adding to @ISA, a marker interface is kind of ugly. One solution is to move part of the work to the abstract marker class:
package Item; sub import { push @{caller().'::ISA'}, __PACKAGE__; }
So, at least there's precedent out there for mussing around with @ISA using import().

In reply to Abusing Exporter for Conditional Inheritance by mojotoad

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.