in reply to NonMoose and (clean) inheritance

Not quite sure what you're asking. Are you looking for a way to change the default for an attribute in a subclass?

package ClassB; use Moose; extends 'ClassA'; has '+param2' => (default => 'PARAM2-CLASSB'); around FOREIGNBUILDARGS => sub { my $orig = shift; my $class = shift; return $class->$orig(param1=>'PARAM1-CLASSB',@_); };

Or better yet, use builders instead of defaults:

package ClassA; use Moose; use MooseX::NonMoose; extends 'aNonMooseClass'; has 'param2' => ( isa=>'Str', builder => '_build_param2'); sub FOREIGNBUILDARGS { my $class = shift; my %args = @_; my $param1 = exists $args{param1} ? $args{param1} : $class->_build +_param1; return ( $param1 ); } sub _build_param1 { return 'Default param1 in class A'; } sub _build_param2 { return 'Default param2 in class A'; } package ClassB; use Moose; extends 'ClassA'; sub _build_param1 { return 'PARAM1-CLASSB'; } sub _build_param2 { return 'PARAM2-CLASSB'; }
use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

Replies are listed 'Best First'.
Re^2: NonMoose and (clean) inheritance
by eco (Acolyte) on Mar 20, 2014 at 21:08 UTC

    Thanks for your answer! My preferred declaration of ClassB is as follows:

    package ClassB; use Moose; extends 'ClassA'; has '+param1' => (default => 'PARAM1-CLASSB'); has '+param2' => (default => 'PARAM2-CLASSB');

    But since this doesn't work for the param1, I figured to use FOREIGNBUILDARGS and BUILDARGS to have some similarity in usage. Your builders solution seems to do this better though. So thank you very much for the idea!

    But if I could change ClassA to allow above syntax for ClassB that would be awesome

    -- ecocode

      Builders are just generally a better idea than defaults. (MooseX::Manual::BestPractices even tells you so.) They give you a nice clean way to override the behaviour in subclasses.

      If you use Moo or MooseX::AttributeShortcuts then you can even do:

      has foo => (is => 'ro', builder => sub { ... });

      ... and it will automatically get "translated" to:

      has foo => (is => 'ro', builder => '_build_foo'); sub _build_foo { ... }

      ... so builders can be just as convenient as defaults are.

      use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

        Thanks for the link of Moose best practices. I didn't know about that one! It's true that builders are preferred over defaults, but it also specifies "However, do use a default when the default is a non-reference.." which happens to be the case here. But hence, for now your solution with builders is the best I have...

        -- ecocode