On Wed, Mar 02, 2011 at 11:36:07AM -0600, Mark A. Stratman wrote:
> On Mar 2, 2011, at 9:23 AM, matthew couchman (JIC) wrote:
> > I'd like to subclass a non moose class Math::VectorReal so that I can do
> > this
>
> > But its not working, I guess because of the first caveat on the manual page
> > that says that references must be the same between the moose class and the
> > non-moose class. I'm a bit lost to be honest, could someone point me in
> > the right direction? >
> The problem is that Math::VectorReal uses an arrayref for its internal
> structure. It does a bless([] ...), but MooseX::NonMoose likes hashrefs.
> I think MooseX::NonMoose::InsideOut should take care of it. Something like
> this:
Yes, MooseX::NonMoose::InsideOut is the right answer here.
> package BetterVector;
> use Moose;
> use MooseX::NonMoose::InsideOut; # NOTE - different module
> use namespace::autoclean;
> extends 'Math::VectorReal';
>
> has [qw(x y z)] => (
> isa => 'Num',
> is => 'ro', # NOTE - 'ro', not 'rw'.... more on this below
> );
>
> sub FOREIGNBUILDARGS {
> my ($class, %vals) = @_;
> return map { $vals{$_} } qw(x y z); # NOTE - Math::VR requires args in a
> specific order, but WE shouldn't.
> }
>
> no Moose;
>
> package main;
> use Modern::Perl;
> my $v = BetterVector->new(x => 1, y => 2, z => 0.5);
> say $v->length;
But you don't want to do it this way, really... overriding the
attributes that already exist in Math::VectorReal isn't useful, and will
cause issues (as mentioned). Something like this should be sufficient:
package BetterVector;
use Moose;
use MooseX::NonMoose::InsideOut;
use namespace::autoclean;
extends 'Math::VectorReal';
# don't declare x, y, and z as moose attrs
# (but you can declare other attrs if you want)
# and make sure moose doesn't see them when they come into the
# constructor
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
my $args = $class->$orig(@_);
delete $args->{$_} for qw(x y z);
$args;
};
# and then this is the same
sub FOREIGNBUILDARGS {
my $class = shift;
my %vals = @_;
return map { $vals{$_} } qw(x y z);
}
no Moose;
1;
This way, Math::VectorReal is still handling the things it knows about
on its own, and you can add new attributes beyond those if you want in a
way that doesn't interfere with anything it's doing.
-doy