docdurdee has asked for the wisdom of the Perl Monks concerning the following question:

Dearest Monks, I use Math::Vector::Real with XS (I'll refer to it as MVR) as a core dependency of my molecular object system. MVR exports the function V that creates the MVR object (a vector of numbers that has useful methods). e.g. atomic coordinates are MVR objects. My classes use the methods of MVR within a Role. Instances of my classes use the V function:
my $atom = Atom->new(Z=> 80, coords => [V(0,0,0), V(1,1,1), V(2,2,2)]) +;
creates a mercury atom with three MVR coordinates. The coords attribute is an ArrayRef-MVR with Array traits; I push_coords, get_coords, set_coords etc. I have two goals: 1. be able to use MVR's V function without having to add use Math::Vector::Real to every script. 2. be able to add MooseX::Storage capabilities for MVR to my classes. So I'm trying to subclass MVR:
package MyMVR; #ABSTRACT: Moose subclass of Math::Vector::Real use 5.008; use Moose; use namespace::autoclean; use MooseX::NonMoose; use MooseX::Storage; with Storage ('io' => 'StorableFile' ); extends 'Math::Vector::Real'; __PACKAGE__->meta->make_immutable; 1;
now using MVR->new works,
use MyMVR; my $a = MyMVR->new(0,0,0); my $b = MyMVR->new(1,1,1); print $_ ."\n" foreach (@{$a - $b});
with Moose warnings (that make sense) about MyMVR's new: "The new() method for MyMVR expects a hash reference or a key/value list. You passed an odd number of arguments at MyMVR_test.pl". The V function is no longer accessible. Any help achieving either goal is greatly appreciated! D

Replies are listed 'Best First'.
Re: subclassing Math::Vector::Real with MooseX::NonMoose
by tobyink (Canon) on Sep 12, 2013 at 14:47 UTC

    Firstly, Moose defaults to instances being blessed hashes; MVR seems to used blessed arrayrefs. So use MooseX::NonMoose::InsideOut instead of plain MooseX::NonMoose.

    Secondly, you probably want to write a FOREIGNBUILDARGS method for your class. This translates the arguments passed to your class' constructor into a list of argument that the parent class' constructor expects.

    Lastly, if you want to use this V function, then you'll need to import it into each namespace where you're using it:

    use Math::Vector::Real qw(V);
    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
    /div
      quickly adding this and MX::Nonmoose::InsideOut to MyMVR:
      sub FOREIGNBUILDARGS { return @{$_[2]}}
      @_ is (class, key (vec), and value (arrayref)) from the adjusted script:
      use MyMVR; my $a = MyMVR->new(vec=>[0,0,0]); my $b = MyMVR->new(vec=>[1,1,1]); print $_ ."\n" foreach (@{$a - $b}); print $a->dist($b) . "\n";
      which works. Thanks!
Re: subclassing Math::Vector::Real with MooseX::NonMoose
by salva (Canon) on Sep 12, 2013 at 15:44 UTC
      Good to know. I'm not sure I understand why yet, so I'll come back to the storage issue later. Thanks Salva.