Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Re: Passing an import list to Moose extends

by choroba (Bishop)
on May 03, 2018 at 21:23 UTC ( #1214027=note: print w/replies, xml ) Need Help??

in reply to Passing an import list to Moose extends

I still struggle to find an imaginable use case. strict isn't an object class.

Also, how would you specify the import arguments for a non-Moose class inherited via parent or base?

Here's what I've played with:


package My::Parent; use warnings; use strict; sub import { my $name = { short => 'frob', long => 'frobnicate' }->{ $_[1] }; no strict 'refs'; *{$name} = *_frobnicate; } sub new { bless $_[1], $_[0] } sub _frobnicate { $_[0]{a} + $_[0]{b} } __PACKAGE__

Plus a test to show how it works:

#!/usr/bin/perl use warnings; use strict; use Test::More tests => 1; use My::Parent 'long'; my $p = 'My::Parent'->new( { a => 2, b => 3 } ); is $p->frobnicate, 5, 'frobnicates';

Inheriting via parent is possible, just note that the import method would be inherited, but you can override it and call the SUPER class's method:


package My::SimpleChild; use warnings; use strict; use parent 'My::Parent'; sub import { shift->SUPER::import('short'); } __PACKAGE__

And it works:

#!/usr/bin/perl use warnings; use strict; use Test::More tests => 1; use My::SimpleChild; my $s = 'My::SimpleChild'->new({ a => 2, b => 3 }); is $s->frob, 5, 'frobs';

In fact, you can use the same trick in Moose. I just added MooseX::NonMoose that handles inheriting from non-Moose classes correctly, and defined the a and b as proper attributes. For it to work, I needed to specify FOREIGNBUILDARGS so I can call the constructor without a hash reference:


package My::MooseChild; use Moose; use MooseX::NonMoose; extends 'My::Parent'; has a => (is => 'ro'); has b => (is => 'ro'); sub import { shift->SUPER::import('short') } sub FOREIGNBUILDARGS { my ($class, %args) = @_; \%args } no Moose; __PACKAGE__->meta->make_immutable

And again, it works.

#!/usr/bin/perl use warnings; use strict; use Test::More tests => 1; use My::MooseChild; my $m = 'My::MooseChild'->new(a => 2, b => 3); is $m->frob, 5, 'frobs';

I'm not sure I'd go that way, though. I remember some monks preferred delegation over inheritance, and we can use it here, too:


package My::DelegChild; use Moose; use My::Parent 'short'; has a => (is => 'ro'); has b => (is => 'ro'); has _parent => (is => 'ro', lazy => 1, default => sub { my ($self) = @_; 'My::Parent'->new({ a => $self->a, b => $self->b }); }, handles => ['frob']); no Moose; __PACKAGE__->meta->make_immutable

#!/usr/bin/perl use warnings; use strict; use Test::More tests => 1; use My::DelegChild; my $ch = 'My::DelegChild'->new(a => 2, b => 3); is $ch->frob, 5, 'frobs';

It can all get very fragile and weird, because the import method changes the global state (and imagine what would happen if the parent's import method used state $name instead of my). It might be impossible to have two classes, each using different import parameters of the base class.

($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1214027]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (10)
As of 2018-07-20 14:58 GMT
Find Nodes?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?

    Results (437 votes). Check out past polls.