Further to my previous answer, here's another way to do it. It pushes all the ugly out to an attribute trait.
use v5.14;
use strict;
use warnings;
# The ugly lives in this package
package MooseX::UnionInheritedTypeConstraint {
use Moose::Role;
use Moose::Util::TypeConstraints -all;
use namespace::clean -except => ['meta'];
around new => sub {
my ($orig, $class, $name, %options) = @_;
if (my $new = $options{isa}) {
my $existing = $options{associated_class}
-> find_attribute_by_name($name)
-> type_constraint;
if ($existing) {
$new = Moose::Util::TypeConstraints::find_or_parse_typ
+e_constraint($new)
unless ref $new;
$options{isa} = union([$existing, $new]);
}
}
$class->_process_isa_option($name, \%options);
# maybe need to process coerce too??
return $class->$orig($name, %options);
};
}
# No ugly below!
package KeyAtom {
use Moose;
has data => (
is => 'rw',
isa => 'Str | RegexpRef',
);
}
package ValAtom {
use Moose;
extends 'KeyAtom';
has '+data' => (
traits => [ 'MooseX::UnionInheritedTypeConstraint' ],
isa => 'ArrayRef | HashRef',
);
}
ValAtom->new(data => 'Hello'); # Str
ValAtom->new(data => qr{Hello}); # RegexpRef
ValAtom->new(data => []); # ArrayRef
ValAtom->new(data => {}); # HashRef
ValAtom->new(data => \*STDOUT); # none of the above... crash!
You might notice that I've managed to avoid the dependency on MooseX::Types here; though the trait should work equally well if you're using MooseX::Types.
PS: You can actually see the code that Moose uses to check type constraints. This is sometimes handy...
my $tc = ValAtom->meta->get_attribute('data')->type_constraint;
say $tc->_inline_check('$value') if $tc->can_be_inlined;
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.