Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以访问Perl中动态指定类中的静态方法吗?_Perl_Oop - Fatal编程技术网

我可以访问Perl中动态指定类中的静态方法吗?

我可以访问Perl中动态指定类中的静态方法吗?,perl,oop,Perl,Oop,可以在Perl中动态指定一个类并访问该类中的静态方法吗?这不起作用,但说明了我想做什么: use Test::Class1; my $class = 'Test::Class1'; $class::static_method(); 我知道我能做到: $class->static_method(); 忽略传递给static_方法的类名,但我想知道是否有更好的方法 我不知道有什么特别好的方法可以做到这一点,但也有一些不太好的方法,比如这个

可以在Perl中动态指定一个类并访问该类中的静态方法吗?这不起作用,但说明了我想做什么:

    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分钟的时间。:)呃,我是说花。。当然是富有成效的+1
      can
      是我做这件事最不疯狂的方式。它仍然会导致整个继承过程,而::没有这样做,但它可以让您绕过整个传递$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');