1 package Moose::Meta::TypeConstraint::DuckType;
7 use Scalar::Util 'blessed';
8 use List::MoreUtils qw(all);
9 use Moose::Util 'english_list';
11 use Moose::Util::TypeConstraints ();
13 our $AUTHORITY = 'cpan:STEVAN';
15 use base 'Moose::Meta::TypeConstraint';
17 __PACKAGE__->meta->add_attribute('methods' => (
18 accessor => 'methods',
22 my ( $class, %args ) = @_;
24 $args{parent} = Moose::Util::TypeConstraints::find_type_constraint('Object');
26 my $self = $class->_new(\%args);
28 $self->compile_type_constraint()
29 unless $self->_has_compiled_type_constraint;
35 my ( $self, $type_or_name ) = @_;
37 my $other = Moose::Util::TypeConstraints::find_type_constraint($type_or_name);
39 return unless $other->isa(__PACKAGE__);
41 my @self_methods = sort @{ $self->methods };
42 my @other_methods = sort @{ $other->methods };
44 return unless @self_methods == @other_methods;
46 while ( @self_methods ) {
47 my $method = shift @self_methods;
48 my $other_method = shift @other_methods;
50 return unless $method eq $other_method;
59 my @methods = @{ $self->methods };
63 return all { $obj->can($_) } @methods
67 sub _compile_hand_optimized_type_constraint {
70 my @methods = @{ $self->methods };
76 && blessed($obj) ne 'Regexp'
77 && all { $obj->can($_) } @methods;
81 sub create_child_type {
82 my ($self, @args) = @_;
83 return Moose::Meta::TypeConstraint->new(@args, parent => $self);
90 if ($self->has_message) {
91 return $self->SUPER::get_message(@_);
94 my @methods = grep { !$value->can($_) } @{ $self->methods };
95 my $class = blessed $value;
97 . " is missing methods "
98 . english_list(map { "'$_'" } @methods);
103 # ABSTRACT: Type constraint for duck typing
111 This class represents type constraints based on an enumerated list of
116 C<Moose::Meta::TypeConstraint::DuckType> is a subclass of
117 L<Moose::Meta::TypeConstraint>.
123 =item B<< Moose::Meta::TypeConstraint::DuckType->new(%options) >>
125 This creates a new duck type constraint based on the given
128 It takes the same options as its parent, with several
129 exceptions. First, it requires an additional option, C<methods>. This
130 should be an array reference containing a list of required method
131 names. Second, it automatically sets the parent to the C<Object> type.
133 Finally, it ignores any provided C<constraint> option. The constraint
134 is generated automatically based on the provided C<methods>.
136 =item B<< $constraint->methods >>
138 Returns the array reference of required methods provided to the
141 =item B<< $constraint->create_child_type >>
143 This returns a new L<Moose::Meta::TypeConstraint> object with the type
146 Note that it does I<not> return a C<Moose::Meta::TypeConstraint::DuckType>
153 See L<Moose/BUGS> for details on reporting bugs.