【问题标题】:Giving alternate name to a module in Perl在 Perl 中为模块提供备用名称
【发布时间】:2013-08-31 12:34:42
【问题描述】:

是否可以在 Perl 中为模块分配一个新名称以在我们的代码中使用?

我的目的是:我的一些客户想要 .xls 文件(电子表格::Excel)和其他 .xlsx(Excel::Writer::XLSX)。由于这两个模块共享它们的大部分 API,我希望能够在项目开始时在某个地方设置一次该选项,然后忘记它,这也便于将来更改它。它也可能用于诸如鼠标/驼鹿变化之类的事情。

【问题讨论】:

    标签: perl module naming


    【解决方案1】:

    看来您真正想要的只是能够在名称在运行时确定的类上调用类方法(如new)。这其实很简单:

    my $spreadsheet_class = 'Spreadsheet::Excel';
    my $sheet = $spreadsheet_class->new;
    

    当您在包含字符串的标量变量上调用方法时,Perl 将其视为该名称的包上的类方法。不需要花哨的符号表技巧,它在use strict 下工作得很好。

    【讨论】:

    • 确实如此,我所做的只是在不同位置的模块上调用new。我以为use strict 也会抱怨这个(就像它抱怨'软参考'),但实际上并没有,所以这很有效。也让我更容易控制这个名称的范围。谢谢!
    • 是否存在这样的情况,这还不够,@amon 的解决方案是必要的?
    • 它只允许你调用类方法。如果您需要执行$Class::config_var = 1; 之类的操作,则需要使用@amon 的解决方案(或启用符号引用)。
    【解决方案2】:

    您可以将类的包存储别名为新名称:

    use strict; use warnings; use feature 'say';
    
    package Foo;
    sub new { bless [] => shift }
    sub hi  { say "hi from Foo" }
    
    package main;
    
    # Alias the package to a new name:
    local *F:: = *Foo::;  # it could make sense to drop the "local"
    
    # make an objects
    my $f = F->new;
    
    # say hi!
    say $f;
    $f->hi;
    

    输出:

    Foo=ARRAY(0x9fa877c)
    hi from Foo
    

    另一种解决方案是动态子类化您想要的包。

    use strict; use warnings; use feature 'say';
    
    package Foo;
    sub new { bless [] => shift }
    sub hi  { say "hi from Foo" }
    
    package Whatever;
    # no contents
    
    package main;
    
    # let Whatever inherit from Foo:
    # note that I assign, instead of `push` or `unshift` to guarantee single inheritance
    @Whatever::ISA = 'Foo'; 
    
    # make an objects
    my $w = Whatever->new;
    
    # say hi!
    say $w;
    $w->hi;
    

    输出:

    Whatever=ARRAY(0x9740758)
    hi from Foo
    

    这两种解决方案都在运行时工作并且非常灵活。第二种解决方案依赖较少的魔法,而且看起来更干净。但是,有可能模块测试ref($obj) eq 'Foo' 而不是正确的blessed $obj and $obj->isa('Foo'),这可能会导致损坏。

    【讨论】:

    • 很好的答案,谢谢!作为旁注,我自己在一些地方使用ref($obj) eq 'Classname' 表单,现在正在更改它们。 :)
    • @sundar blessed 当然是Scalar::Util::blessed (只是确保这很清楚)。如果您比较ref-equality,子类将不起作用。 blessed 测试确保我们不会收到任何 Can't call method "isa" on unblessed reference 错误。
    • 你刚刚重写了Package::Alias
    • 如果您只需要在运行时确定的类上调用类方法,这将是严重的过度杀伤。
    • @cjm 确实,我想得太复杂了。谢谢你的回答。
    猜你喜欢
    • 2019-08-15
    • 2011-02-08
    • 2020-12-24
    • 2018-10-02
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    相关资源
    最近更新 更多