如何在不影响主程序包的情况下对长包名称进行别名?

时间:2016-10-12 00:40:12

标签: perl perl-stash

如果我有一个非常长的包名,我可以通过在符号表中输入一个别名来包含该包:

BEGIN {
    # Make "Alias" be an alias for "Some::Really::Long::Package";
    *Alias:: = \*Some::Really::Long::Package::;
    # Equivalent to:
    # *main::Alias:: = \*Some::Really::Long::Package::;
}

这就是Package::Alias之类的内容。然而,这很糟糕,因为它与main包混淆了。如何使别名仅影响当前包,并且只能使用包中的别名?我尝试将别名定义更改为

*Short::Alias:: = \*Some::Really::Long::Package::;

但是我必须使用Short::Alias->myMethod()而不是Alias->myMethod()

use strict;
use warnings;

package Some::Really::Long::Package;

sub myMethod {
    print "myMethod\n";
}

package Short;

BEGIN {
    # Make "Alias" be an alias for "Some::Really::Long::Package";
    *Short::Alias:: = \*Some::Really::Long::Package::;
}

# I want this to work
Alias->myMethod();

package main;

# I want this to not work
Alias->myMethod();

加分如果Alias->myMethod()Alias::myMethod()都在Short包中,而不在main中。

1 个答案:

答案 0 :(得分:6)

由于您不想修改main的符号表,因此您可以创建一个" package-local"别名

package Short;

use constant Alias => 'Some::Really::Long::Package'; # create alias
Alias->myMethod(); # correctly calls myMethod() of package Some::Really::Long::Package

或者

package Short;

sub Alias { Some::Really::Long::Package:: } # create alias
Alias->myMethod(); # correctly calls myMethod() of package Some::Really::Long::Package

两个示例都应按预期工作。因此,任何从包Alias->myMethod()致电main的尝试都会失败

  

找不到对象方法" myMethod"通过包" Alias" (也许你忘了加载" Alias"?)

因为符号表%main::%::没有名为Alias::的条目。

由于您在一个文件中有多个package来电,因此您还可以创建$alias来引用Some::Really::Long::Package。然后,您可以将$alias的范围限制为包Short,以使其无法从其他位置访问:

package Short;
{
   my $alias = Some::Really::Long::Package::; # create alias
   $alias->myMethod(); # correctly calls myMethod() of package Some::Really::Long::Package
}

编辑(作为对编辑问题的回复):

更新的问题是:

  

Alias->myMethod()Alias::myMethod()都可以在Short包中使用,但不能在main中使用吗?

我不这么认为。

有几种方法可以使用->语法,但不能使用::语法。这是因为perl似乎假设像Alias这样的简单字后跟包分隔符::代表包Alias中的包main

package Short;

Alias::myMethod();           # if you call myMethod(), you actually call it ...

::Alias::myMethod();         # ... like this, which is equivalent ...

main::Alias::myMethod();     # ... to this

所有三个呼叫选项都是等效的,这表明了一个重要的事实。如果perl遇到Foo::之类的内容,它会首先在包main中查找而不是从当前(相对)位置查找。因此,如果我在这里没有遗漏某些内容,则无法在未将Alias::myMethod()添加到Alias::的情况下使用main

  

这就是Package::Alias之类的内容。但是,这很糟糕,因为它与main包混淆了。

现在,我上面描述的内容也可以解释为什么像Package::Alias这样的模块会修改你的main包,因为似乎无法避免它。