How can I export a normal, non-OO subroutine from a Moose package? In a regular package, I'd do it with Exporter
, @ISA
and @EXPORT
.
CodePudding user response:
Moose is for building classes and roles. While you technically can also export functions, it's not necessarily the best idea.
Here's an example Moose class which also exports a function.
MyApp/Widget.pm
use v5.26;
use warnings;
package MyApp::Widget;
use Exporter qw( import );
our @EXPORT_OK = qw( is_widget );
use Moose;
use namespace::autoclean -except => 'import';
has name => ( is => 'ro', isa => 'Str', required => 1 );
sub is_widget {
my $object = shift;
blessed( $object ) and $object->isa( __PACKAGE__ );
}
__PACKAGE__->meta->make_immutable;
Here's how you might use it:
use v5.26;
use warnings;
use MyApp::Widget qw( is_widget );
my $w = 'MyApp::Widget'->new( name => 'Foo' );
say is_widget( $w );
say $w->is_widget;
Note that even though is_widget
was intended an exportable function, it can also be called as a method! In this case, that's a feature rather than a bug, but often that will be an inconvenience.
A better idea might be to create two separate packages: one for your class and one for your exportable functions.
MyApp/Widget.pm
use v5.26;
use warnings;
package MyApp::Widget;
use Moose;
use namespace::autoclean;
has name => ( is => 'ro', isa => 'Str', required => 1 );
__PACKAGE__->meta->make_immutable;
MyApp/Util.pm
use v5.26;
use warnings;
package MyApp::Util;
use Exporter qw( import );
our @EXPORT_OK = qw( is_widget );
use Scalar::Util qw( blessed );
sub is_widget {
my $object = shift;
blessed( $object ) and $object->isa( 'MyApp::Widget' );
}
1;
And you'd call use your packages like this:
use v5.26;
use warnings;
use MyApp::Widget;
use MyApp::Util qw( is_widget );
my $w = 'MyApp::Widget'->new( name => 'Foo' );
say is_widget( $w );
Because the Moose class and the Exporter are now cleanly separated, you can no longer call $w->is_widget
— it's entirely a function and no longer a method.