Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re: Passing an import list to Moose extends

by choroba (Cardinal)
on May 03, 2018 at 21:23 UTC ( [id://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:

My/Parent.pm

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:

My/SimpleChild.pm

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:

My/MooseChild.pm

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:

My/DelegChild.pm

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?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1214027]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2024-03-28 20:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found