0

I'm just trying to do this: http://modernperlbooks.com/mt/2011/08/youre-already-using-dependency-injection.html. Really not deviating too much at all from that example code.

Here's what I've got:

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;

It's worth noting that the M::new! message never appears, so I'm guessing that it's never reached. What's going on?

Nander Speerstra
  • 1,496
  • 6
  • 24
  • 29

2 Answers2

2

With Moose, you shouldn't write sub new. Moose provides the constructor for you.

Also, using Exporter makes no sense with object-oriented modules. The following program works for me:

#!/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');
choroba
  • 231,213
  • 25
  • 204
  • 289
  • Where, specifically, do you mean, please? –  Sep 07 '16 at 09:34
  • Thank you. The problem was exactly as you said - no need for "sub new". In fact the sub in question seems to bu... stuff up the whole thing. Either "sub new" in M or Foo seems to do it. –  Sep 07 '16 at 09:48
  • 1
    @DiamondGeezer: "Thank you" on StackOverflow = vote up / accept :-) – choroba Sep 07 '16 at 09:50
  • Indeed, but one needs more rep before one is able to do that :-D –  Sep 07 '16 at 10:17
  • 1
    Lots of OO modules export constants, though `use Exporter; @ISA = qw( Exporter );` has been replaced with `use Exporter qw( import );` – ikegami Sep 07 '16 at 15:48
1

You have a solution - don't write your own new() method when you're using Moose. But there's one other little point that might be worth making.

The constructor that Moose will give you for your Foo class will work pretty well as a drop-in replacement for your new() method. But the one that Moose gives you for your M class will be missing a feature - it won't print your "M::new!\n" message. How do we get round that?

In Moose, you can define a BUILD() method which will be called immediately after new() has returned a new object. That's a good place to put any extra initialisation that your new object needs. It would also be be a good place for your print() call (although it happens after object construction, not before - so it's not an exact replacement).

Dave Cross
  • 68,119
  • 3
  • 51
  • 97