【问题标题】:In Perl, how can I call a method whose name I have in a string?在 Perl 中,如何调用字符串中名称的方法?
【发布时间】:2011-02-12 17:42:42
【问题描述】:

我正在尝试编写一些抽象代码,用于在相似对象列表中搜索其属性与特定值匹配的第一个对象。为了做到这一点,我需要调用一堆访问器方法并一个一个地检查它们的所有值。我想使用这样的抽象:

sub verify_attribute {
    my ($object, $attribute_method, $wanted_value) = @_;
    if ( call_method($object, $attribute_method) ~~ $wanted_value ) {
        return 1;
    }
    else {
        return;
    }
}

然后我可以遍历一个散列,其键是访问器方法名称,其值是我正在寻找这些属性的值。例如,如果该哈希被称为%wanted,我可能会使用这样的代码来查找我想要的对象:

my $found_object;
FINDOBJ: foreach my $obj (@list_of_objects) {
    foreach my $accessor (keys %wanted) {
        next FINDOBJ unless verify_attribute($obj, $accessor, $wanted{$accessor});
    }
    # All attrs verified
    $found_object = $obj;
    last FINDOBJ;
}

当然,唯一的问题是call_method 不存在。或者是吗?如果我有一个包含方法名称的字符串,如何调用方法?或者对整个问题有更好的解决方案吗?

【问题讨论】:

    标签: perl string oop methods symbols


    【解决方案1】:
    my $found_object;
    FINDOBJ: foreach my $obj (@list_of_objects) {
      foreach my $accessor (keys %wanted) {
        next FINDOBJ unless $obj->$accessor() == $wanted{$accessor};
      }
      # All attrs verified
      $found_object = $obj;
      last;
    }
    

    是的,您可以通过这种方式调用方法。不涉及字符串(或任何其他)评估。 另外,根据数据的类型,将== 替换为eq=~...

    或者,对于一些额外的学分,以函数方式执行:(all() 确实应该是 List::Util 的一部分!)

    use List::Util 'first';
    
    sub all (&@) {
      my $code = shift;
      $code->($_) || return 0 for @_;
      return 1;
    }
    
    my $match = first {
                        my $obj = $_;
                        all { $obj->$_ == $attrs{$_} }
                          keys %wanted
                      } @list_of_objects;
    

    更新:诚然,第一个解决方案是不太混淆的解决方案,所以它是可取的。但作为回答问题的人,你也添加了一点糖来让它变得有趣! ;-)

    【讨论】:

    • 是的,我只是在几秒钟前通过反复试验才弄清楚这一点。酷。
    • 我只使用List::AllUtils。或Util::Any qw( :all )。但在我的示例代码中,我试图坚持核心。
    • 我相信要使此功能起作用,您必须使用no strict;(不一定是全局)禁用严格性检查——对吗?
    • @j_random_hacker:对于 $obj->$method?没有。根本不干扰“使用严格”。如果这就是你的想法,它不是一个象征性的参考。
    • @j_random_hacker => 我猜想为什么 $obj->$method 语法可以使用 strict 是因为它只是这个合法结构的语法糖:$obj->can($method)->($obj)。而$func->()&{$func}() 没有任何“严格的法律”形式
    【解决方案2】:

    功能方式很酷,但对于像我这样的傻瓜评估规则:

    test.pl

    #!/usr/bin/perl -l
    use F;
    my $f = F->new();
    
    my $fun = 'lol'; # method of F
    
    eval '$f->'.$fun.'() '; # call method of F, which name is in $fun var
    

    F.pm

    package F;
    
    sub new
    {
        bless {};
    }
    
    
    sub lol
    {
        print "LoL";
    }
    1;
    

    [root@ALT-24 root]# perl test.pl

    大声笑

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 2014-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多