我正在写一个大多数是静态的函数。我想将它插入Template Toolkit,它传递类名。实质上,它正在做
ClassName->function( $args.. )
但我希望它能像
那样做ClassName::function( $args.. )
里面
sub function {
}
处理这两种情况的正确方法是什么?
答案 0 :(得分:7)
一般来说,没有。 a sub
要么被编写为方法,要么不是。
通过将包名称添加到参数列表中,了解File::Spec::Functions如何处理这种情况。
现在, 在一个非常具体的,有限的案例中 ,您可以这样做:
shift if $_[0] eq __PACKAGE__;
作为sub中的第一行,当sub
被称为类方法时,丢弃第一个参数。
答案 1 :(得分:6)
这是一个更安全的版本,结合了Sinan's和Alan's个答案,还有:
ClassName::function("ClassName")
误解为方法调用代码:
if (@_ == $nArgsExpectedForThisFunc + 1) {
$_[0] eq __PACKAGE__ || UNIVERSAL::isa($_[0], __PACKAGE__) || die;
shift;
}
这要求您知道预期的参数数量;如果不这样做,但是您的第一个参数可以与作为方法调用时可能发送的可能允许值区分开(例如,如果您的第一个参数必须是arrayref),则仍然可以应用相同的一般原则。
答案 2 :(得分:4)
模板工具包期望它的插件使用OO,因此无法提供该接口。如果你还想要一个功能界面,你有几个选择。
Perl并没有真正区分函数和方法。主要区别在于方法调用语法隐式地将对象引用(或类名,取决于它的调用方式)作为第一个参数。您可以使用函数调用语法并手动提供指示对象:
ClassName::function('ClassName', @args);
但那太乱了。更清洁的解决方案是将其拆分为两个子,其中一个包装为另一个。 e.g。
package ClassName;
sub function {
# do something
}
sub method {
my $class = shift;
function(@_);
}
该函数也可以是该方法的包装器。正如Sinan所提到的,File :: Spec通过创建两个模块来实现这一点:一个带有OO接口,另一个带有功能接口。