开发者

Is there a Perl module or technique that makes using long namespaces easier?

开发者 https://www.devze.com 2023-02-11 08:21 出处:网络
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:

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
0

精彩评论

暂无评论...
验证码 换一张
取 消