Perl + moose:无法在未定义的值上调用方法“x”

时间:2016-09-07 09:28:55

标签: perl moose

我只是想这样做:http://modernperlbooks.com/mt/2011/08/youre-already-using-dependency-injection.html。真的没有从示例代码中偏离太多。

这就是我所拥有的:

package M;
use Moose;
use Exporter;
use Data::Dumper;

sub new {
    print "M::new!\n";
    my $class = shift;
    return bless {}, $class;
}

sub x {
    my ($self, $stuff) = @_;

    print Dumper($stuff);
}


#################################


package Foo;
use Moose;
use Exporter;

our @ISA = qw(Exporter);
our @EXPORT = ();

has 'mS', is => 'ro', default => sub { M->new };

sub new {
    my $class = shift;
    return bless {}, $class;
}

sub bar {
    my ($self, $data) = @_;

    # do stuff here...
    # ...


    my $foo = $self->mS;
    # this...
    $foo->x($data);
    # ...causes "Can't call method "x" on an undefined value at Foo.pm line 45."
}

1;

值得注意的是M::new!消息永远不会出现,所以我猜它永远不会到达。发生了什么事?

2 个答案:

答案 0 :(得分:2)

使用Moose,您不应该写sub new。 Moose为您提供构造函数。

此外,使用Exporter对于面向对象的模块毫无意义。以下程序适合我:

#!/usr/bin/perl

{   package M;
    use Moose;
    use Data::Dumper;

    sub x {
        my ($self, $stuff) = @_;
        print Dumper($stuff);
    }
}


{   package Foo;
    use Moose;

    has mS => ( is => 'ro', default => sub { 'M'->new } );

    sub bar {
        my ($self, $data) = @_;
        my $foo = $self->mS;
        $foo->x($data);
    }
}

my $foo = 'Foo'->new;
$foo->bar('test');

答案 1 :(得分:1)

您有一个解决方案 - 当您使用Moose时,请不要编写自己的new()方法。但还有一点可能是值得的。

Moose将为您的Foo类提供的构造函数可以很好地替代new()方法。但是,Moose为你的M班提供的那个将缺少一个功能 - 它不会打印你的" M :: new!\ n"信息。我们如何绕过那个?

在Moose中,您可以定义BUILD()方法,该方法将在new()返回新对象后立即调用。这是一个放置新对象所需的额外初始化的好地方。这也是您print()电话的好地方(尽管对象构建之后发生,而不是之前 - 因此它不是确切的替代品。)