I have a number of different sites that I download data from and massage into other formats (using Perl) for use at work, that are all run from one Perl script kinda like so:
#! /usr/bin/perl
use strict;
use My::Package1;
use My::Package2;
my $p1 = My::Package1->new;
$p1->download;
my $p2 = My::Package2->new;
$p2->download;
and so on and so forth. At the moment each My::Package
is its own package; it doesn't inherit from a base package or anything. I am planning to re-write them using Moose
and I was hoping that rather than having to edit the Perl script that runs the download each time a new package is added, there might be a way of finding packages that inherit from a base package, and then in a loop instantiate each and do the downloading, kinda like so:
#! /usr/bin/perl
use strict;
for my $pname (packages_that_inherit_from("My::Package")) {
my $package = $pname->new;
$package->download;
}
Is it, or something ilke it, possible?
TIA
Using Moose
's Class::MOP
underpinning you can find the subclasses assigned to each class (at that point in time).
From Class::MOP::Class
docs:
$metaclass->subclasses This returns a list of all subclasses for this class, even indirect subclasses.
$metaclass->direct_subclasses This returns a list of immediate subclasses for this class, which does not include indirect subclasses.
So for example if we build these classes:
{
package Root;
use Moose;
use namespace::clean -except => 'meta';
sub baz { say 'Some root thingy' }
sub download { say "downloading from " . __PACKAGE__ }
}
{
package NodeA;
use Moose;
extends 'Root';
use namespace::clean -except => 'meta';
sub download { say "downloading from " . __PACKAGE__ }
}
{
package NodeA1;
use Moose;
extends 'NodeA';
use namespace::clean -except => 'meta';
sub download { say "downloading from " . __PACKAGE__ }
}
Then using your example as a basis we can do this:
for my $pname ( Root->new->meta->direct_subclasses ) {
my $package = $pname->new;
$package->download;
}
# => "downloading from NodeA"
So above runs NodeA->download
. Changing above to meta->subclasses
would also run the NodeA1->download
.
/I3az/
Although you say you are moving to Moose
, a non-Moose
way is to put all the derived packages in the known subdirectory based on the base package name. You then load all of the modules
For instance, if your base package is Local::Downloader
, all the derived packages start with Local::Downloader::Plugin
or something similar. You then look for all modules in your @INC
that much .../Local/Downloader/Plugin/...
. Although it's not too hard to do yourself, something like Module::PluginFinder can do it for you too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With