views:

220

answers:

2

Here's something weird that I can't figure out. I have a Moose class that I also want to export some constants, using the age-old standard Exporter module. However, as soon as I add extends Exporter to my class, for some reason, the default Moose constructor no longer gets inherited and I get the fatal error:

Can't locate object method "new" via package "MyApp::Dispatch"

Here is a simple test which demonstrates the problem.

package Foo;
use Moose;
use constant NARF => 'poit';
extends 'Exporter';

1;

$ perl -I./lib -MFoo -e '$f=Foo->new'
Can't locate object method "new" via package "Foo" at -e line 1.

Removing the extends line makes the problem vanish.

This is using Moose 0.93.

+4  A: 

It is assuming you are inheriting from another Moose-based class, so it doesn't inherit from Moose::Object. I'm not sure what the standard answer would be: just manually adding Moose::Object or somehow using MooseX::NonMoose or something else.

But Exporter works just fine even when not inherited; just import its import routine:

use Exporter "import";
ysth
Well, that should have been obvious, shouldn't it? I feel dumb tonight. :) I've even used MooseX::NonMoose before, so I should have thought of that, but didn't. Anyway, importing `import` rather than inheriting works fine.
friedo
Moose's `extends` is equivalent to `@ISA = @list`. If this list is empty at compile time Moose will automatically put `Moose::Object` into @ISA for you.
perigrin
@perigrin: that was basically what I said.
ysth
+2  A: 

You already got the real answer, but the real question is why do you have a module that exports stuff and is an object? That's a pretty weird design, and may be a code smell.

Dave Rolsky
The exports are constants which are used by callbacks registered by other parts of the system; I agree it's a little weird and will probably end up rethinking the design sooner or later. But it works for now.
friedo