Some namespaces are long and annoying. Lets say that i downloaded hypothetical package called FooFoo-BarBar-BazBaz.tar.gz, and it has the following modules:
FooFoo::BarBar::BazBaz::Bill
FooFoo::BarBar::BazBaz::Bob
FooFoo::BarBar::BazBaz::Ben
FooFoo::BarBar::BazBaz::Bozo
FooFoo::BarBar::BazBaz::Brow开发者_StackOverflow中文版n
FooFoo::BarBar::BazBaz::Berkly
FooFoo::BarBar::BazBaz::Berkly::First
FooFoo::BarBar::BazBaz::Berkly::Second
Is there a module or technique I can use that's similar to the C++ 'using' statement, i.e., is there a way I can do
using FooFoo::BarBar::BazBaz;
which would then let me do
my $obj = Brown->new();
ok $obj->isa('FooFoo::BarBar::BazBaz::Brown') ; # true
# or...
ok $obj->isa('Brown'); # also true
The aliased pragma does this:
use aliased 'FooFoo::BarBar::BazBaz::Bill';
my $bill = Bill->new;
aliased
is syntactic sugar for
use constant Bill => 'FooFoo::BarBar::BazBaz::Bill';
# or
sub Bill () {'FooFoo::BarBar::BazBaz::Bill'}
The downside of this is that normal usage of package names as arguments is done with quoted strings:
$obj->isa('FooFoo::BarBar::BazBaz::Bill')
But the constant subroutine needs to be a bare word:
$obj->isa(Bill);
Which just seems like a bug waiting to happen.
Alternatively, you could just use Perl's builtin support for namespace aliasing:
package Foo::Bar::Baz::Bill;
sub new {bless {}}
package Foo::Bar::Baz::Tom;
sub new {bless {}}
package main;
BEGIN {*FBB:: = *Foo::Bar::Baz::} # the magic happens here
say FBB::Bill->new; # Foo::Bar::Baz::Bill=HASH(0x80fd10)
say FBB::Tom->new; # Foo::Bar::Baz::Tom=HASH(0xfd1080)
Regarding the ->isa('shortname')
requirement, the aliased stash method works with quoted strings as usual:
my $obj = FBB::Bill->new;
say $obj->isa('FBB::Bill'); # prints 1
say $obj->isa('Foo::Bar::Baz::Bill'); # prints 1
The effect of a compile time alias BEGIN {*short:: = *long::package::name::}
is global across all packages and scopes. This is fine as long as you pick an empty package to alias into.
If the module only needs to have class methods called on it then subclassing it is the simplest solution. This can of course be done dynamically at runtime to select where Bill goes.
push @Bill::ISA, "FooFoo::BarBar::BazBaz::Bill";
print Bill->isa("FooFoo::BarBar::BazBaz::Bill");
1
sub FooFoo::BarBar::BazBaz::Bill::yo {
print "FooFoo::BarBar::BazBaz::Bill here\n";
}
Bill->yo
FooFoo::BarBar::BazBaz::Bill here
精彩评论