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

Chr*_*ris 5 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::;
}
Run Code Online (Sandbox Code Playgroud)

这就是Package::Alias你内心所做的事情.然而,这很糟糕,因为它与main包装混乱.如何使别名仅影响当前包,并且只能使用包中的别名?我尝试将别名定义更改为

*Short::Alias:: = \*Some::Really::Long::Package::;
Run Code Online (Sandbox Code Playgroud)

但后来我不得不使用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();
Run Code Online (Sandbox Code Playgroud)

奖励积分,如果双方Alias->myMethod()Alias::myMethod()工作的Short包,而不是在main.

ref*_*ind 6

由于您不想修改符号表main,因此可以使用创建"包本地"别名

package Short;

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

或者

package Short;

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

这两个例子都应该按预期工作.因此,任何Alias->myMethod()从包调用的尝试main都会失败

无法通过包"别名"找到对象方法"myMethod"(也许你忘了加载"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
}
Run Code Online (Sandbox Code Playgroud)

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

更新的问题是:

既可以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
Run Code Online (Sandbox Code Playgroud)

所有三个呼叫选项都是等效的,这表明了一个重要的事实.如果perl遇到类似的东西Foo::,它会先开始查看包,main而不是从当前(相对)位置查看.所以,如果我不是在这里失去了一些东西,你不能使用Alias::myMethod()不添加Alias::main.

这就是Package::Alias你内心所做的事情.然而,这很糟糕,因为它与main包装混乱.

现在,我上面描述的内容也解释了为什么模块会Package::Alias修改你的main包,因为似乎没有办法避免它.