Perl包:如何将类导入到';使用';r';名称空间?
我正在开发一个为其“父”包定义异常的包(使用Perl包:如何将类导入到';使用';r';名称空间?,perl,exception-handling,namespaces,packages,perl-module,Perl,Exception Handling,Namespaces,Packages,Perl Module,我正在开发一个为其“父”包定义异常的包(使用Exception::Class::Nested)。不过,我不希望父包必须使用非常长的名称,也不希望污染任何其他名称空间 所以我想做的是将类名的最后一个元素导出到包的名称空间中,该包使用异常包 例如,异常包的摘录: package Klass:Foo::Bar::Exceptions; use vars qw( @ISA @EXPORT @EXPORT_OK ... ); @ISA = qw( Klass::Foo::Bar Exporter ); u
Exception::Class::Nested
)。不过,我不希望父包必须使用非常长的名称,也不希望污染任何其他名称空间
所以我想做的是将类名的最后一个元素导出到包的名称空间中,该包使用异常包
例如,异常包的摘录:
package Klass:Foo::Bar::Exceptions;
use vars qw( @ISA @EXPORT @EXPORT_OK ... );
@ISA = qw( Klass::Foo::Bar Exporter );
use Exception::Class::Nested 0.04 (
'Klass::Foo::Bar::Exceptions::BaseClass' => {
description => 'Base class for exceptions',
'Klass::Foo::Bar::Exceptions::NameError' => {
error => "I don't like your face"
}
}
);
“父”包:
package Klass::Foo::Bar;
use Klass::Foo::Bar::Exceptions;
Klass::Foo::Bar::Exceptions::NameError->throw(error => "D'oh!");
my $e = NameError->new(error => 'Mwahaha!');
我想导出/导入exception类,这样第二次调用(我的$eone)的工作方式就好像NameError
是在Klass::Foo::Bar
中定义的一样,但我还没有弄清楚
(在任何人说'butException::Class
具有漂亮的别名
之前,我要指出,别名专门链接到异常的throw
方法,因此我不能将其用于非自动抛出的new
调用..)
我尝试过的一件事是将其放入异常包的导入器子部分(@snames
是一个完全限定的异常类数组(例如,'Klass::Foo::Bar::Exceptions::namererror'
),或者只是尾部(例如,'namererror'
):
但这最终要求我使用Klass::Foo::Bar::namererror
调用异常,而不仅仅是namererror
我不想将namererror
导入main::
恐怕打字珠和符号表对我来说还是有点神秘
我确信有一种方法可以做我想做的事情(或者我正在做一些我不应该做的事情,但现在让我们先别管它)。有人能帮我吗
谢谢!在您的示例import
sub中,您正在对包隐藏进行别名处理,这并不能满足您的需要。相反,您希望创建具有缩短名称的子例程,以返回完整的包名:
sub import {
my $caller = caller;
for my $long (@{$EXPORT_TAGS{exceptions}}) { # for each full name
my ($short) = $long =~ /([^:]+)$/; # grab the last segment
no strict 'refs';
*{"$caller\::$short"} = sub () {$long}; # install a subroutine named
# $short into the caller's pkg
# that returns $long
}
}
分解最后一行,sub(){$long}
创建一个不带参数的匿名子例程。代码引用包含单个变量$long
,该变量保留了循环迭代期间的值。这称为词法闭包,基本上意味着子例程的编译环境($long
及其值)将与子例程保持相同的时间
然后,此匿名子例程以$short
名称安装到调用者的包中。调用者包中的子例程的完全限定名称是caller::subname
,它由“$caller\::$short”
构造。然后将其作为typeglob*{…}取消引用
。将引用分配给typeglob将填充typeglob的插槽。因此,分配代码引用将安装子例程
换句话说,下面的子例程声明:
sub short () {'a::long::name'}
意思与:
BEGIN {*{__PACKAGE__.'::short'} = sub () {'a::long::name'}}
在您的示例import
sub中,您正在对包隐藏进行别名处理,这并不能满足您的需要。相反,您希望创建具有缩短名称的子例程,以返回完整的包名:
sub import {
my $caller = caller;
for my $long (@{$EXPORT_TAGS{exceptions}}) { # for each full name
my ($short) = $long =~ /([^:]+)$/; # grab the last segment
no strict 'refs';
*{"$caller\::$short"} = sub () {$long}; # install a subroutine named
# $short into the caller's pkg
# that returns $long
}
}
分解最后一行,sub(){$long}
创建一个不带参数的匿名子例程。代码引用包含单个变量$long
,该变量保留了循环迭代期间的值。这称为词法闭包,基本上意味着子例程的编译环境($long
及其值)将与子例程保持相同的时间
然后,此匿名子例程以$short
名称安装到调用者的包中。调用者包中的子例程的完全限定名称是caller::subname
,它由“$caller\::$short”
构造。然后将其作为typeglob*{…}取消引用
。将引用分配给typeglob将填充typeglob的插槽。因此,分配代码引用将安装子例程
换句话说,下面的子例程声明:
sub short () {'a::long::name'}
意思与:
BEGIN {*{__PACKAGE__.'::short'} = sub () {'a::long::name'}}
我不太清楚它在做什么,但它是有效的。我必须研究它才能理解它。谢谢!!!我不太清楚它在做什么,但它是有效的。我必须研究它才能理解它。谢谢!!!