I have a base class and a dozen derived classes. All but one derived class require an attribute with a name key. So I could add it to the eleven derived classes and leave the eleventh one.
However, laziness is what it is, I would like to add an attribute to the base class, thereby avoiding repeating the declaration eleven times and adding what I think is consistency and simplicity.
Now this creates a problem for a single class that does not require an attribute key. Note that there is no harm if this class has this attribute, but it does not require it.
My idea was to resolve this using a flag method is_strictthat is called from BUILDARGSto decide whether keyor not to. Here is a simple script example to illustrate this (well, I inverted the concept, an attribute keyis required only in one case (instead of all cases except one), but this problem remains under the influence of this inversion):
package Bla;
use Moose;
use Carp ();
has grop => is => 'ro', isa => 'Str';
has key => is => 'ro', isa => 'Int';
sub is_strict { 0 }
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
my $args = @_ == 1 ? shift : { @_ };
Carp::croak 'key missing'
if not exists $args->{key}
and $class->is_strict;
return $class->$orig( @_ );
};
no Moose; __PACKAGE__->meta->make_immutable;
package Bla::Eins;
use Moose; extends 'Bla';
no Moose; __PACKAGE__->meta->make_immutable;
package Bla::Zwei;
use Moose; extends 'Bla';
no Moose; __PACKAGE__->meta->make_immutable;
package Bla::Drei;
use Moose; extends 'Bla';
override is_strict => sub { 1 };
no Moose; __PACKAGE__->meta->make_immutable;
package main;
use Test::More;
use Test::Exception;
lives_ok { Bla::Eins->new };
lives_ok { Bla::Zwei->new };
throws_ok { Bla::Drei->new } qr/key missing/;
lives_ok { Bla::Drei->new( key => 99 ) };
done_testing;
It works, but is there a better way to achieve what I want?
source
share