如何编写一个既可用作普通子程序又可用作类方法的Perl子程序?

Tim*_*mmy 3 perl

我正在写一个大多数是静态的函数.我想将它插入Template Toolkit,它传递类名.实质上,它正在做

ClassName->function( $args.. )
Run Code Online (Sandbox Code Playgroud)

但是我想让它做点什么

ClassName::function( $args.. )
Run Code Online (Sandbox Code Playgroud)

sub function {
}
Run Code Online (Sandbox Code Playgroud)

处理这两种情况的正确方法是什么?

Sin*_*nür 7

一般来说,没有.a sub要么被编写为方法,要么不是.

通过将包名称添加到参数列表中,了解File :: Spec :: Functions如何处理这种情况.

现在,在一个非常具体的,有限的情况下,您可以:

shift if $_[0] eq __PACKAGE__;
Run Code Online (Sandbox Code Playgroud)

作为你的sub中的第一行,在sub被称为类方法时丢弃第一个参数.

  • +1.如果每个函数都使用固定数量的参数,这会变得更安全,在这种情况下,您可以根据是否有比预期更多的参数来决定是否使用OO调用语法.(就目前而言,调用"ClassName :: function('ClassName');"将触发误报.) (2认同)

j_r*_*ker 6

这是一个更安全的版本,结合了思南艾伦的答案,还有:

  • 处理从派生对象调用方法的可能性
  • 不会误解ClassName::function("ClassName")为方法调用

代码:

if (@_ == $nArgsExpectedForThisFunc + 1) {
    $_[0] eq __PACKAGE__ || UNIVERSAL::isa($_[0], __PACKAGE__) || die;
    shift;
}
Run Code Online (Sandbox Code Playgroud)

这要求您知道期望的参数数量; 如果不这样做,但是您的第一个参数可以与作为方法调用时可能发送的可能允许值区分开(例如,如果您的第一个参数必须是arrayref),则仍然可以应用相同的一般原则.