【问题标题】:Hash of ref functions inside Perl modulePerl 模块中 ref 函数的散列
【发布时间】:2015-01-28 14:55:46
【问题描述】:

我正在尝试编写一个模块,该模块应该能够根据变量的内容调用特定的方法。我决定使用哈希将这些名称映射到函数引用。我已经编写了一些概念验证代码来看看这是否可行,并且在此过程中遇到了一些问题。

我遇到了引用函数调用无法访问我的 $self->... 数据成员的问题。

下面是实际的复制粘贴概念验证示例,用于显示我遇到的问题。

#!/usr/bin/env perl
use strict;
use warnings;

package My::Test;

sub new {
    my $class = shift;
    my $self = {};

    $self->{_currentType} = undef;
    $self->{_currentData} = undef;
    $self->{_mapping} = undef;

    return bless $self, $class;
}

# Setup the mapping
sub createMapping {
    my $self = shift;

    my %mapping = ( 'mapping.1' => \&My::Test::handler1,
                    'mapping.2' => \&My::Test::handler2,
                    'mapping.3' => \&My::Test::handler3, );

    $self->{_mapping} = \%mapping;
}

# This is the main entrypoint for actual processing where the appropriate handler function is invoked.
sub startMeUp {
    my ($self, $mapType, $someDataToHandle) = @_;

    $self->{_currentType} = $mapType;
    $self->{_currentData} = $someDataToHandle;

    # Now call this function
    $self->{_mapping}->{$mapType}->();
}

# These functions below gets called, but the values of $self are not retained. Why?
sub handler1 {
    my $self = shift;
    print "I am a handler for $self->{_currentType}!\n";
}

sub handler2 {
    my $self = shift;
    print "I am a handler for $self->{_currentType}!\n";
}

sub handler3 {
    my $self = shift;
    print "I am a handler for $self->{_currentType}!\n";
}

sub manualFunction {
    my $self = shift;
    print "I am a manual call, I am $self->{_currentType}!\n";
}

1;

然后通过一个简单的调用者脚本调用上述模块,如下所示:

#!/usr/bin/env perl
use strict;
use warnings;

use My::Test;

my $test = My::Test->new();
$test->createMapping();

# We want to try to execute the handler2 function (mapping.2 is mapped to handler2 via createMapping).
# The function call works but when done this way, I cannot use
# $self->{someVariableName} to access module members as I'd like.
$test->startMeUp('mapping.2');

# The follow will work.
$test->manualFunction();

运行 perl 脚本会产生以下结果:

% perl test.pl                                                                                                                               
Use of uninitialized value in concatenation (.) or string at My/Test.pm line 48.
I am a handler for !
I am a manual call, I am mapping.2!

我在寻找解决方案时遇到问题,为什么通过哈希表调用引用的 startMeUp 函数不保留 $self->{some class member variable here }

我已尝试搜索有关此问题的 SO,但无法找到有关此特定问题的问题/答案。

我不确定在这种情况下我想要做的事情是否根本不可能,或者我是否只是做错了,所以我希望你们中的一些人能指出我正确的方向。

(当然,只为三个元素实现这样的解决方案是矫枉过正的,但在实际实现中会明显更多,我宁愿避免编写一个好的 if-elsif 语句,它也是很好的练习)。

提前谢谢你!

最好的问候, 克劳斯

【问题讨论】:

  • @dgw 写了什么或$self->{_mapping}{$mapType}->($self);
  • uninitialized value 对我来说是一个很大的警钟 - 看起来 self 是未定义的。我认为那是因为你是 mapping 对子的引用,而不是 OO 调用。

标签: perl hash reference module


【解决方案1】:

如果您从

更改映射设置
sub createMapping {
    my $self = shift;

    my %mapping = ( 'mapping.1' => \&My::Test::handler1,
                    'mapping.2' => \&My::Test::handler2,
                    'mapping.3' => \&My::Test::handler3, );

    $self->{_mapping} = \%mapping;
}

sub createMapping {
    my $self = shift;

    my %mapping = ( 'mapping.1' => sub { $self->handler1 } ,
                    'mapping.2' => sub { $self->handler2 } ,
                    'mapping.3' => sub { $self->handler3 } );

    $self->{_mapping} = \%mapping;
}

您的测试脚本将起作用。

&My::Test::handler1 会将handler1 作为简单函数调用,而不是作为对象方法。

【讨论】:

  • 经过测试,效果很好。非常感谢您的示例和解释!
猜你喜欢
  • 2019-10-26
  • 1970-01-01
  • 2014-05-19
  • 1970-01-01
  • 1970-01-01
  • 2012-08-03
  • 2011-03-13
  • 2014-01-16
  • 2011-03-13
相关资源
最近更新 更多