我可以访问Perl中动态指定类中的静态方法吗?
可以在Perl中动态指定一个类并访问该类中的静态方法吗?这不起作用,但说明了我想做什么:我可以访问Perl中动态指定类中的静态方法吗?,perl,oop,Perl,Oop,可以在Perl中动态指定一个类并访问该类中的静态方法吗?这不起作用,但说明了我想做什么: use Test::Class1; my $class = 'Test::Class1'; $class::static_method(); 我知道我能做到: $class->static_method(); 忽略传递给static_方法的类名,但我想知道是否有更好的方法 我不知道有什么特别好的方法可以做到这一点,但也有一些不太好的方法,比如这个
use Test::Class1;
my $class = 'Test::Class1';
$class::static_method();
我知道我能做到:
$class->static_method();
忽略传递给static_方法的类名,但我想知道是否有更好的方法 我不知道有什么特别好的方法可以做到这一点,但也有一些不太好的方法,比如这个程序:
#!/usr/bin/perl -w
use strict;
package Test::Class1;
sub static_method {
print join(", ", @_) . "\n";
}
package main;
my $class = "Test::Class1";
{
no strict "refs";
&{${class}. "::static_method"}(1, 2, 3);
}
我已经包含了一个$class
变量,因为这是您提出问题的方式,它说明了如何在运行时选择类名,但是如果您事先知道该类,您可以轻松地调用&{“Test::Class1::static_method”}(1,2,3)代码>
请注意,如果已打开,则必须关闭严格的“参考”
。您可以使用字符串:
输出:
C:\Temp> z
1, 2, 3
Rate eval can nostrict
eval 12775/s -- -94% -95%
can 206355/s 1515% -- -15%
nostrict 241889/s 1793% 17% --
输出:
C:\Temp> z
1, 2, 3
Rate eval can nostrict
eval 12775/s -- -94% -95%
can 206355/s 1515% -- -15%
nostrict 241889/s 1793% 17% --
价格评估可以预测
评估12775/s--94%-95%
can 206355/s 1515%--15%
诺斯特里克241889/s 1793%17%--
是的!狭窄的方法是使用
can
返回对方法的引用,未定义/错误。然后,只需使用dereferene语法调用该方法
它给出:
> perl foobar.pl
yup it can, and it Passed in '' and ran baz!
>perl foobar.pl
是的,它可以,它通过了,跑了巴兹!
调用静态函数有三种主要方式:
$object->static\u method()
Classname->static\u method()
Classname::static\u method()
# callable as $object->static_method() or Classname->static_method()
sub static_method
{
my $class = shift; # ignore; not needed
# ...
}
或者像这样,它可以在所有三种调用场景中工作,并且不会像Robert p的解决方案那样在调用方产生任何开销:
use UNIVERSAL qw(isa);
sub static_method
{
my $class = shift if $_[0] and isa($_[0], __PACKAGE__);
# ...
}
与Perl一样
- 您可以使用特殊的
变量访问符号表%:
my $class = 'Test::Class'; my @depth = split '::', $class; my $ref = \%::; $ref = $glob->{$_.'::'} for @depth; # $::{'Test::'}{'Class::'} $code = $glob->{'static_method'}; $code->('Hello','World');
- 你可以简单地使用一个
- 也可以使用字符串
- 在这种情况下,最简单的方法是使用
- @Tim我现在明白了。对不起,不必要的编辑。我发布了一个使用string
eval
的解决方案,以展示使用您的代码作为模板的另一种方法。@Sinan没问题!让我有机会进一步解释并首次使用“回滚”功能。:-)我现在想知道没有严格的“refs”和eval方法的优缺点是什么。如果子例程未定义,则两者都报告相同的错误。从速度的角度来看,没有严格的“参考”
方法似乎是明显的赢家(只做了一个简单的测试)。我也倾向于避开任何涉及eval”“
的解决方案。我忘了可以
。向您展示了我很少做这样的事情。感谢您为并列比较解决方案付出的额外努力。看来,can
在性能上没有受到严格的“参照”
的影响,这也是最明显的方法。我被投票赞成帮助我浪费雇主15分钟的时间。:)呃,我是说花。。当然是富有成效的+1can
是我做这件事最不疯狂的方式。它仍然会导致整个继承过程,而::没有这样做,但它可以让您绕过整个传递$self/$classname作为$\u0]的行为。至少,如果它是一个模块,那么很可能没有“父”模块。我没有见过这样的例子,但是从父类继承方法的非类模块似乎有点奇怪。让我想知道它是否有很好的用途…@Robert P:在有父级的模块中,静态类函数肯定有很好的用途。e、 g.我今天刚刚为一系列缓存处理程序写了一篇文章,其中子缓存中的静态函数包含一些配置信息,需要增强父缓存中的某些行为。可能值得明确指出的是,如果您要查找的静态函数不在用于调用can()的包中
然后,这种方法将遵循任何@ISA
定义,尝试在派生此函数的其他基本包中查找静态函数。这可能是也可能不是你所追求的行为。
use strict;
use warnings;
{
package Test::Class;
sub static_method{ print join(' ', @_), "\n" }
}
my $class = 'Test::Class';
my @depth = split '::', $class;
my $ref = \%::;
$ref = $glob->{$_.'::'} for @depth; # $::{'Test::'}{'Class::'}
$code = $glob->{'static_method'};
$code->('Hello','World');
no strict 'refs';
my $code = &{"${class}::static_method"};
# or
my $code = *{"${class}::static_method"}{CODE};
$code->('Hello','World');
eval "${class}::static_method('Hello','World')";
$code = $class->can('static_method');
$code->('Hello','World');