support requires on Mouse::Role.
Tokuhiro Matsuno [Tue, 2 Dec 2008 04:01:08 +0000 (04:01 +0000)]
lib/Mouse/Meta/Role.pm
lib/Mouse/Role.pm
t/033-requires.t [new file with mode: 0644]
t/400-define-role.t

index 07203c3..ebb929f 100644 (file)
@@ -2,6 +2,7 @@
 package Mouse::Meta::Role;
 use strict;
 use warnings;
+use Carp 'confess';
 
 do {
     my %METACLASS_CACHE;
@@ -27,13 +28,20 @@ sub new {
     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;
@@ -49,6 +57,12 @@ sub apply {
     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);
index 2f44a75..057761a 100644 (file)
@@ -51,7 +51,11 @@ sub extends  { confess "Roles do not support 'extends'" }
 
 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'" }
 
diff --git a/t/033-requires.t b/t/033-requires.t
new file mode 100644 (file)
index 0000000..da4f10f
--- /dev/null
@@ -0,0 +1,25 @@
+#!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 { }
+}
+
index 66cddb0..aa7f598 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 use strict;
 use warnings;
-use Test::More tests => 12;
+use Test::More tests => 11;
 use Mouse::Util ':test';
 
 lives_ok {
@@ -68,15 +68,6 @@ throws_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;