2016-09-07 2 views
0

Я просто пытаюсь сделать это: http://modernperlbooks.com/mt/2011/08/youre-already-using-dependency-injection.html. На самом деле не отклонять слишком много от этого примера кода.Perl + moose: Невозможно вызвать метод «x» по неопределенному значению

Вот что я получил:

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! сообщение, поэтому я предполагаю, что он никогда не достиг. Что происходит?

+0

С [Moose] (http://p3rl.org/Moose), не записывается 'sub new'. – choroba

ответ

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'); 
+0

Где, в частности, вы имеете в виду, пожалуйста? –

+0

@DiamondGeezer: проверьте обновление. – choroba

+0

Спасибо. Проблема была в точности так же, как вы сказали, - нет необходимости в «sub new». На самом деле вопрос, о котором идет речь, кажется, это ... все это. Либо «sub new» в M, либо Foo, похоже, это делает. –

1

У вас есть решение - не написать свой собственный new() метод, когда вы используете Муза. Но есть еще один маленький момент, который стоит сделать.

Конструктор, который Moose предоставит вам для вашего класса Foo, будет работать очень хорошо, как замена на замену вашего метода new(). Но тот, который Moose дает вам для вашего класса M, не будет иметь никакой функции - он не будет печатать ваше сообщение «M :: new! \ N». Как мы обходим это?

В Moose вы можете определить метод BUILD(), который вызывается сразу после того, как new() вернул новый объект. Это хорошее место, чтобы добавить дополнительную инициализацию, необходимую вашему новому объекту. Это также было бы хорошим местом для вашего звонка print() (хотя бывает после объект строительства, а не раньше - так что это не точная замена).