【问题标题】:Variable / Constant in UNIVERSAL?UNIVERSAL 中的变量/常量?
【发布时间】:2011-09-15 19:13:09
【问题描述】:

我确定我的问题与命名空间和范围有关,但我需要一些帮助!

我正在编写一个 OO Perl 脚本,其中包含相当多的类,并且要求最大限度地减少外部模块的使用(不要问...我知道,我知道...)

所以,我想使用 UNIVERSAL 来提供每个对象都可以使用的日志记录方法。

这是我刚刚编写的一个非常简单的示例。

use strict;
use warnings;

package House;
sub new {
    my ( $class, %args ) = @_;
    my $self = {
        colour => $args{colour},
        size   => $args{size},
    };
    bless $self, $class;
    return $self;
}

package Boat;
sub new {
    my ( $class, %args ) = @_;
    my $self = {
        doors => $args{doors},
        roof  => $args{roof},
    };
    bless $self, $class;
    return $self;
}

package main;
my $obj = Boat->new( colour => "red", size => "big" );
$obj->_logger("created a big red boat");

my $obj2 = House->new( doors => 1, roof => "yes" );
$obj2->_logger("created a house with a door and roof");

package UNIVERSAL;
use POSIX qw( strftime );
use Sys::Hostname;
my $error_log
    = hostname() . "-" . strftime( "%Y-%m-%d_%H.%M", localtime ) . ".log";

sub _dump {
    my ( $self, $data, $filepath ) = @_;
    open my $fh, ">", $filepath or die "Cannot write to $filepath: $!";
    print $fh $data;
}

sub _logger {
    my ( $self, $data ) = @_;
    my $timestamp = strftime( "%Y-%m-%d %H:%M:%S", localtime );
    $self->_dump( $timestamp . " " . $data, $error_log );
}
__END__

问题是 UNIVERSAL 命名空间中的 $error_log 变量似乎无法被其他类中的对象以与 UNIVERSAL 方法相同的方式访问。

my $error_log 的错误: 在 ./test_uni.pl 第 47 行打开时使用未初始化的值 $filepath。 在 ./test_uni.pl 第 47 行的连接 (.) 或字符串中使用未初始化的值 $filepath。 无法写入:./test_uni.pl 第 47 行没有这样的文件或目录。

实际上,现在我输入这个我想知道在 UNIVERSAL 中使用类方法的闭包是否可以工作。

当我去尝试的时候,请问有人对我有什么建议吗?

谢谢!

==================== 更新 =======================

在 UNIVERSAL 中使用类方法的闭包似乎有效:

package UNIVERSAL;
use POSIX qw( strftime );
use Sys::Hostname;

{
    sub ERROR_LOG {
    return hostname() . "-" . strftime( "%Y-%m-%d_%H.%M", localtime ) . ".log";
    }
}

然后我在UNIVERSAL::_loggerUNIVERSAL->ERROR_LOG 中调用它。

但是!我只希望在运行时创建一次 ERROR_LOG 文件路径。有了这个,它每次都会评估它......

这是唯一的方法吗?如何从其他地方访问 UNIVERSAL 包中的变量?

谢谢!

【问题讨论】:

    标签: perl


    【解决方案1】:

    您的问题只是在设置 UNIVERSAL 中的内容之前运行代码。

    将主包一直向下移动,或者将 UNIVERSAL 包裹在 BEGIN 块中,它可以工作。

    UNIVERSAL 或我在这里的表现没有什么奇怪的。


    更新:好吧,你可以调用 _logger 有点奇怪(所以该部分已经加载),但 $error_log 还没有。这是一个演示此行为的最小示例(删除 BEGIN 块以查看问题):

    use strict;
    use warnings;
    
    ABC->hey();
    
    package ABC;
    BEGIN{
      my $x = 1;
      sub hey(){
        print "x =  $x";
      }
    }
    

    也许this 解释它:

    my 同时具有编译时和运行时效果。在编译时,编译器会注意到它。这样做的主要用途是安静地使用 strict 'vars' ,但它对于 perlref 中详述的闭包的生成也是必不可少的。但是,实际初始化会延迟到运行时,因此它会在适当的时间执行,例如每次通过循环时。

    我的解读是变量声明和子程序是在代码执行之前编译的,但是值的分配直到再次到达执行它的行(在你的情况下是在你之后调用子程序,这些子程序是围绕仍未​​初始化的值的闭包)。

    【讨论】:

    • 谢谢!我认为文件中的位置无关紧要......我会测试一下。
    猜你喜欢
    • 1970-01-01
    • 2017-08-03
    • 2016-04-21
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2014-01-30
    相关资源
    最近更新 更多