package Mouse::Meta::Role;
use strict;
use warnings;
+use Carp 'confess';
do {
my %METACLASS_CACHE;
my $class = shift;
my %args = @_;
- $args{attributes} ||= {};
+ $args{attributes} ||= {};
+ $args{required_methods} ||= [];
bless \%args, $class;
}
sub name { $_[0]->{name} }
+sub add_required_methods {
+ my $self = shift;
+ my @methods = @_;
+ push @{$self->{required_methods}}, @methods;
+}
+
sub add_attribute {
my $self = shift;
my $name = shift;
my $self = shift;
my $class = shift;
+ for my $name (@{$self->{required_methods}}) {
+ unless ($class->name->can($name)) {
+ confess "'@{[ $self->name ]}' requires the method '$name' to be implemented by '@{[ $class->name ]}'";
+ }
+ }
+
for my $name ($self->get_attribute_list) {
next if $class->has_attribute($name);
my $spec = $self->get_attribute($name);
sub with { confess "Mouse::Role does not currently support 'with'" }
-sub requires { confess "Mouse::Role does not currently support 'requires'" }
+sub requires {
+ my $meta = Mouse::Meta::Role->initialize(caller);
+ Carp::croak "Must specify at least one method" unless @_;
+ $meta->add_required_methods(@_);
+}
sub excludes { confess "Mouse::Role does not currently support 'excludes'" }
--- /dev/null
+#!perl
+use strict;
+use warnings;
+use Test::More tests => 1;
+use Mouse::Util ':test';
+
+{
+ package Foo;
+ use Mouse::Role;
+ requires 'foo';
+}
+
+throws_ok {
+ package Bar;
+ use Mouse;
+ with 'Foo';
+} qr/'Foo' requires the method 'foo' to be implemented by 'Bar'/;
+
+{
+ package Baz;
+ use Mouse;
+ with 'Foo';
+ sub foo { }
+}
+
#!/usr/bin/env perl
use strict;
use warnings;
-use Test::More tests => 12;
+use Test::More tests => 11;
use Mouse::Util ':test';
lives_ok {
package Role;
use Mouse::Role;
- requires 'required';
-
- no Mouse::Role;
-} qr/Mouse::Role does not currently support 'requires'/;
-
-throws_ok {
- package Role;
- use Mouse::Role;
-
excludes 'excluded';
no Mouse::Role;