替换Perl中的类(“覆盖"/“扩展"具有相同名称的类)? [英] Replacing a class in Perl ("overriding"/"extending" a class with same name)?
问题描述
我正在尝试在Perl中迭代目录,变得自省对象作为结果,主要是这样,当我在IO::All
的返回值上使用Dumper
时,我可以打印类似mtime
的字段.
I am trying to Iterate directories in Perl, getting introspectable objects as result, mostly so I can print fields like mtime
when I'm using Dumper
on the returns from IO::All
.
我发现,如果在模块IO::All::File
中(对我来说是/usr/local/share/perl/5.10.1/IO/All/File.pm
),我添加了行field mtimef => undef;
,然后修改其sub file
,以便它运行$self->mtimef($self->mtime);
,就可以做到这一点. (请注意,该字段不能与相应的方法/属性具有相同的名称(mtime
),因为这些字段在IO::All
中动态分配).因此,从本质上讲,我对重载"不感兴趣,就像对多个函数签名使用相同的名称一样-我想用扩展版本替换"或覆盖"一个类(不确定如何实现)适当地称呼),但使用相同的名称;因此,所有其他可能使用它的类将从那时起继续使用扩展版本.
I have discovered, that it can be done, if in the module IO::All::File
(for me, /usr/local/share/perl/5.10.1/IO/All/File.pm
), I add the line field mtimef => undef;
, and then modify its sub file
so it runs $self->mtimef($self->mtime);
(note, this field cannot have the same name (mtime
) as the corresponding method/property, as those are dynamically assigned in IO::All
). So, in essence, I'm not interested in "overloading", as in having the same name for multiple function signatures - I'd want to "replace" or "override" a class with its extended version (not sure how this is properly called), but under the same name; so all other classes that may use it, get on to using the extended version from that point on.
现在对我来说最好的方法是,如果可以以某种方式从实际的可运行的" Perl脚本中替换" IO::All::File
类,如果可以的话,可以使用继承机制,所以我可以添加什么是额外".为了说明我的意思,下面是一个示例:
The best approach for me now would be, if I could somehow "replace" the IO::All::File
class, from my actual "runnable" Perl script -- if somehow possible, by using the mechanisms for inheritance, so I can just add what is "extra". To show what I mean, here is an example:
use warnings;
use strict;
use Data::Dumper;
my @targetDirsToScan = ("./");
use IO::All -utf8 ; # Turn on utf8 for all io
# try to "replace" the IO::All::File class
{ # recursive inheritance!
package IO::All::File;
use IO::All::File -base;
# hacks work if directly in /usr/local/share/perl/5.10.1/IO/All/File.pm
field mtimef => undef; # hack
sub file {
my $self = shift;
bless $self, __PACKAGE__;
$self->name(shift) if @_;
$self->mtimef($self->mtime); # hack
return $self->_init;
}
1;
}
# main script start
my $io = io(@targetDirsToScan);
my @contents = $io->all(0); # Get all contents of dir
for my $contentry ( @contents ) {
print Dumper \%{*$contentry};
}
...失败,并显示在/usr/local/share/perl/5.10.1/IO/All/Base.pm第13行的包'IO :: All :: Filesys'中检测到递归继承".如果您注释掉递归继承"部分,则一切正常.
... which fails with "Recursive inheritance detected in package 'IO::All::Filesys' at /usr/local/share/perl/5.10.1/IO/All/Base.pm line 13."; if you comment out the "recursive inheritance" section, it all works.
我很清楚为什么使用这种语法会发生这种情况-但是,有没有一种语法或方法可以用来用扩展名但名称相同的类替换"一个类,类似于我上面尝试过的方式?显然,我要使用相同的名称,这样我就不必更改IO::All
中的任何内容(或包中的任何其他文件).另外,我最好在运行程序" Perl脚本中执行此操作(这样我就可以将所有内容保存在一个脚本文件中,而不必维护多个文件)-但是,如果唯一的可能方法是拥有一个单独的脚本.pm
文件,我也想知道.
I'm sort of clear on why this happens with this kind of syntax - however, is there a syntax, or a way, that can be used to "replace" a class with its extended version but of the same name, similar to how I've tried it above? Obviously, I want the same name, so that I wouldn't have to change anything in IO::All
(or any other files in the package). Also, I would preferably do this in the "runner" Perl script (so that I can have everything in a single script file, and I don't have to maintain multiple files) - but if the only way possible is to have a separate .pm
file, I'd like to know about it as well.
那么,有什么我可以使用的技术吗?
So, is there a technique I could use for something like this?
推荐答案
好吧,老实说,我不知道发生了什么,但是我仔细查看了上面的代码,看来所需要做的就是删除use IO::All::File
语句中的-base
;而该代码似乎可以按我预期的那样运行-也就是说,如果您在上面的代码中更改了此代码段,则 does 包将被覆盖":
Well, I honestly have no idea what is going on, but I poked around with the code above, and it seems all that is required, is to remove the -base
from the use IO::All::File
statement; and the code otherwise seems to work as I expect it - that is, the package does get "overriden" - if you change this snippet in the code above:
# ...
{ # no more recursive inheritance!? IO::All::File gets overriden with this?!
package IO::All::File;
use IO::All::File; # -base; # just do not use `-base` here?!
# hacks work if directly in /usr/local/share/perl/5.10.1/IO/All/File.pm
field mtimef => undef; # hack
sub file {
my $self = shift;
bless $self, __PACKAGE__;
$self->name(shift) if @_;
$self->mtimef($self->mtime); # hack
print("!! *haxx0rz'd* file() reporting in\n");
return $self->_init;
}
1;
}
# ...
我觉得这太不可思议了,我什至在其中添加了print()
来确保它运行的是"overriden"功能,而且确实如此.这就是我的输出结果:
I found this so unbelievable, I even added the print()
there to make sure it is the "overriden" function that runs, and sure enough, it is; this is what I get in output:
...
!! *haxx0rz'd* file() reporting in
$VAR1 = {
'_utf8' => 1,
'mtimef' => 1394828707,
'constructor' => sub { "DUMMY" },
'is_open' => 0,
'io_handle' => undef,
'name' => './test.blg',
'_encoding' => 'utf8',
'package' => 'IO::All'
};
...
...当然可以肯定,该字段也在那里...
... and sure enough,the field is there, as expected, too...
嗯-我希望有人最终在这里提出一个更合格的答案;暂时,我希望这和解决我的问题一样好:)
...
Well - I hope someone eventually puts a more qualified answer here; for the time being, I hope this is as good as a fix to my problems :)
...
这篇关于替换Perl中的类(“覆盖"/“扩展"具有相同名称的类)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!