我确定我的问题与命名空间和范围有关,但我需要一些帮助!
我正在编写一个带有相当多类的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。
在串联(。)中使用未初始化的值$ filepath或在./test_uni.pl第47行使用字符串。
无法写入:./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::_logger
在UNIVERSAL->ERROR_LOG
中调用它。
BUT!我只希望在运行时创建一次ERROR_LOG文件路径。有了这个,它每次都会对它进行评估......
这是唯一的方法吗?如何从其他地方访问UNIVERSAL包中的变量?
谢谢!
答案 0 :(得分: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解释了它:
我既有编译时也有运行时效果。在编译时,编译器会注意到它。这样做的主要用处是安静地使用严格的“变量”,但它对于生成闭包也是必不可少的,详见perlref。但是,实际初始化会延迟到运行时间,因此会在适当的时间执行,例如每次循环执行。
我的阅读是在执行代码之前编译变量声明和子程序,但是在再次到达执行它的行之前不会发生值的赋值(在你的情况下是在你之后)调用子程序,这些子程序是仍然未初始化的值周围的闭包。)