foo
[gitmo/Moose.git] / lib / Moose / Role.pm
CommitLineData
e185c027 1
2package Moose::Role;
3
4use strict;
5use warnings;
6
7use Scalar::Util ();
8use Carp 'confess';
9use Sub::Name 'subname';
10
2d562421 11use Sub::Exporter;
12
13our $VERSION = '0.03';
e185c027 14
15use Moose::Meta::Role;
7eaef7ad 16use Moose::Util::TypeConstraints;
e185c027 17
2d562421 18{
19 my ( $CALLER, %METAS );
20
21 sub _find_meta {
7eaef7ad 22 my $role = $CALLER;
2d562421 23
7eaef7ad 24 return $METAS{$role} if exists $METAS{$role};
25
26 # make a subtype for each Moose class
27 subtype $role
28 => as 'Role'
29 => where { $_->does($role) }
30 unless find_type_constraint($role);
2d562421 31
32 my $meta;
7eaef7ad 33 if ($role->can('meta')) {
34 $meta = $role->meta();
2d562421 35 (blessed($meta) && $meta->isa('Moose::Meta::Role'))
36 || confess "Whoops, not møøsey enough";
37 }
38 else {
7eaef7ad 39 $meta = Moose::Meta::Role->new(role_name => $role);
2d562421 40 $meta->_role_meta->add_method('meta' => sub { $meta })
41 }
42
7eaef7ad 43 return $METAS{$role} = $meta;
2d562421 44 }
45
e185c027 46
2d562421 47 my %exports = (
48 extends => sub {
49 my $meta = _find_meta();
50 return subname 'Moose::Role::extends' => sub {
51 confess "Moose::Role does not currently support 'extends'"
52 };
53 },
54 with => sub {
55 my $meta = _find_meta();
56 return subname 'Moose::Role::with' => sub {
57 my ($role) = @_;
58 Moose::_load_all_classes($role);
59 $role->meta->apply($meta);
60 };
61 },
62 requires => sub {
63 my $meta = _find_meta();
64 return subname 'Moose::Role::requires' => sub {
65 $meta->add_required_methods(@_);
66 };
67 },
68 has => sub {
69 my $meta = _find_meta();
70 return subname 'Moose::Role::has' => sub {
71 my ($name, %options) = @_;
72 $meta->add_attribute($name, %options)
73 };
74 },
75 before => sub {
76 my $meta = _find_meta();
77 return subname 'Moose::Role::before' => sub {
78 my $code = pop @_;
79 $meta->add_before_method_modifier($_, $code) for @_;
80 };
81 },
82 after => sub {
83 my $meta = _find_meta();
84 return subname 'Moose::Role::after' => sub {
85 my $code = pop @_;
86 $meta->add_after_method_modifier($_, $code) for @_;
87 };
88 },
89 around => sub {
90 my $meta = _find_meta();
91 return subname 'Moose::Role::around' => sub {
92 my $code = pop @_;
93 $meta->add_around_method_modifier($_, $code) for @_;
94 };
95 },
96 super => sub {
97 my $meta = _find_meta();
98 return subname 'Moose::Role::super' => sub {};
99 },
100 override => sub {
101 my $meta = _find_meta();
102 return subname 'Moose::Role::override' => sub {
103 my ($name, $code) = @_;
104 $meta->add_override_method_modifier($name, $code);
105 };
106 },
107 inner => sub {
108 my $meta = _find_meta();
109 return subname 'Moose::Role::inner' => sub {
110 confess "Moose::Role does not currently support 'inner'";
111 };
112 },
113 augment => sub {
114 my $meta = _find_meta();
115 return subname 'Moose::Role::augment' => sub {
116 confess "Moose::Role does not currently support 'augment'";
117 };
118 },
119 confess => sub {
120 return \&Carp::confess;
121 },
122 blessed => sub {
123 return \&Scalar::Util::blessed;
124 }
125 );
126
127 my $exporter = Sub::Exporter::build_exporter({
128 exports => \%exports,
129 groups => {
130 default => [':all']
131 }
132 });
133
134 sub import {
135 $CALLER = caller();
136
137 # we should never export to main
138 return if $CALLER eq 'main';
139
140 goto $exporter;
141 };
142
e185c027 143}
144
1451;
146
147__END__
148
149=pod
150
151=head1 NAME
152
153Moose::Role - The Moose Role
154
76d37e5a 155=head1 SYNOPSIS
156
157 package Eq;
158 use strict;
159 use warnings;
160 use Moose::Role;
161
e46edf94 162 requires 'equal';
76d37e5a 163
164 sub no_equal {
165 my ($self, $other) = @_;
166 !$self->equal($other);
167 }
168
169 # ... then in your classes
170
171 package Currency;
172 use strict;
173 use warnings;
174 use Moose;
175
176 with 'Eq';
177
178 sub equal {
179 my ($self, $other) = @_;
bdabd620 180 $self->as_float == $other->as_float;
76d37e5a 181 }
182
e185c027 183=head1 DESCRIPTION
184
76d37e5a 185This is currently a very early release of Perl 6 style Roles for
02a0fb52 186Moose, it is still incomplete, but getting much closer. If you are
187interested in helping move this feature along, please come to
188#moose on irc.perl.org and we can talk.
76d37e5a 189
190=head1 CAVEATS
191
02a0fb52 192Currently, the role support has a few of caveats. They are as follows:
e185c027 193
194=over 4
195
76d37e5a 196=item *
197
02a0fb52 198At this time classes I<cannot> correctly consume more than one role. The
199role composition process, and it's conflict detection has not been added
200yet. While this should be considered a major feature, it can easily be
201worked around, and in many cases, is not needed at all.
202
203A class can actually consume multiple roles, they are just applied one
204after another in the order you ask for them. This is incorrect behavior,
205the roles should be merged first, and conflicts determined, etc. However,
206if your roles do not have any conflicts, then things will work just
207fine. This actually tends to be quite sufficient for basic roles.
76d37e5a 208
76d37e5a 209=item *
210
211Roles cannot use the C<extends> keyword, it will throw an exception for now.
212The same is true of the C<augment> and C<inner> keywords (not sure those
213really make sense for roles). All other Moose keywords will be I<deferred>
214so that they can be applied to the consuming class.
215
e185c027 216=back
217
218=head1 BUGS
219
220All complex software has bugs lurking in it, and this module is no
221exception. If you find a bug please either email me, or add the bug
222to cpan-RT.
223
224=head1 AUTHOR
225
226Stevan Little E<lt>stevan@iinteractive.comE<gt>
227
228=head1 COPYRIGHT AND LICENSE
229
230Copyright 2006 by Infinity Interactive, Inc.
231
232L<http://www.iinteractive.com>
233
234This library is free software; you can redistribute it and/or modify
235it under the same terms as Perl itself.
236
237=cut