0_03
[gitmo/Moose.git] / lib / Moose.pm
CommitLineData
fcd84ca9 1
2package Moose;
3
4use strict;
5use warnings;
6
8339fae2 7our $VERSION = '0.03';
fcd84ca9 8
cc65ead0 9use Scalar::Util 'blessed', 'reftype';
fcd84ca9 10use Carp 'confess';
bc1e29b5 11use Sub::Name 'subname';
fcd84ca9 12
7f18097c 13use UNIVERSAL::require;
14
ef1d5f4b 15use Class::MOP;
16
c0e30cf5 17use Moose::Meta::Class;
18use Moose::Meta::Attribute;
7415b2cb 19use Moose::Meta::TypeConstraint;
7c13858b 20use Moose::Meta::TypeCoercion;
c0e30cf5 21
fcd84ca9 22use Moose::Object;
7415b2cb 23use Moose::Util::TypeConstraints;
a15dff8d 24
fcd84ca9 25sub import {
26 shift;
27 my $pkg = caller();
28
fc5609d2 29 # we should never export to main
30 return if $pkg eq 'main';
31
a15dff8d 32 Moose::Util::TypeConstraints->import($pkg);
182134e8 33
34 # make a subtype for each Moose class
7415b2cb 35 subtype $pkg
36 => as Object
37 => where { $_->isa($pkg) };
5569c072 38
fcd84ca9 39 my $meta;
40 if ($pkg->can('meta')) {
41 $meta = $pkg->meta();
42 (blessed($meta) && $meta->isa('Class::MOP::Class'))
43 || confess "Whoops, not møøsey enough";
44 }
45 else {
c0e30cf5 46 $meta = Moose::Meta::Class->initialize($pkg => (
47 ':attribute_metaclass' => 'Moose::Meta::Attribute'
e522431d 48 ));
49 $meta->add_method('meta' => sub {
50 # re-initialize so it inherits properly
51 Moose::Meta::Class->initialize($pkg => (
52 ':attribute_metaclass' => 'Moose::Meta::Attribute'
53 ));
54 })
fcd84ca9 55 }
ad1ac1bd 56
bc1e29b5 57 # NOTE:
58 # &alias_method will install the method, but it
59 # will not name it with
60
61 # handle superclasses
7f18097c 62 $meta->alias_method('extends' => subname 'Moose::extends' => sub {
d7f17ebb 63 foreach my $super (@_) {
64 # see if this is already
65 # loaded in the symbol table
66 next if _is_class_already_loaded($super);
67 # otherwise require it ...
68 ($super->require)
69 || confess "Could not load superclass '$super' because : " . $UNIVERSAL::require::ERROR;
70 }
7f18097c 71 $meta->superclasses(@_)
5e030bec 72 });
505c6fac 73
c0e30cf5 74 # handle attributes
29db16a9 75 $meta->alias_method('has' => subname 'Moose::has' => sub {
76 my ($name, %options) = @_;
77 if (exists $options{is}) {
cc65ead0 78 if ($options{is} eq 'ro') {
79 $options{reader} = $name;
80 }
81 elsif ($options{is} eq 'rw') {
82 $options{accessor} = $name;
83 }
29db16a9 84 }
cc65ead0 85 if (exists $options{isa}) {
e90c03d0 86 # allow for anon-subtypes here ...
66811d63 87 if (blessed($options{isa}) && $options{isa}->isa('Moose::Meta::TypeConstraint')) {
88 $options{type_constraint} = $options{isa};
cc65ead0 89 }
90 else {
e90c03d0 91 # otherwise assume it is a constraint
7c13858b 92 my $constraint = find_type_constraint($options{isa});
e90c03d0 93 # if the constraing it not found ....
94 unless (defined $constraint) {
95 # assume it is a foreign class, and make
96 # an anon constraint for it
66811d63 97 $constraint = subtype Object => where { $_->isa($options{isa}) };
7415b2cb 98 }
e90c03d0 99 $options{type_constraint} = $constraint;
cc65ead0 100 }
29db16a9 101 }
102 $meta->add_attribute($name, %options)
103 });
3c7278fb 104
c0e30cf5 105 # handle method modifers
bc1e29b5 106 $meta->alias_method('before' => subname 'Moose::before' => sub {
e5ebe4ce 107 my $code = pop @_;
108 $meta->add_before_method_modifier($_, $code) for @_;
109 });
bc1e29b5 110 $meta->alias_method('after' => subname 'Moose::after' => sub {
e5ebe4ce 111 my $code = pop @_;
fc5609d2 112 $meta->add_after_method_modifier($_, $code) for @_;
e5ebe4ce 113 });
bc1e29b5 114 $meta->alias_method('around' => subname 'Moose::around' => sub {
c0e30cf5 115 my $code = pop @_;
fc5609d2 116 $meta->add_around_method_modifier($_, $code) for @_;
c0e30cf5 117 });
5569c072 118
c0e30cf5 119 # make sure they inherit from Moose::Object
5569c072 120 $meta->superclasses('Moose::Object')
121 unless $meta->superclasses();
ad1ac1bd 122
c0e30cf5 123 # we recommend using these things
124 # so export them for them
5569c072 125 $meta->alias_method('confess' => \&Carp::confess);
126 $meta->alias_method('blessed' => \&Scalar::Util::blessed);
fcd84ca9 127}
128
d7f17ebb 129sub _is_class_already_loaded {
130 my $name = shift;
131 no strict 'refs';
132 return 1 if defined ${"${name}::VERSION"} || defined @{"${name}::ISA"};
133 foreach (keys %{"${name}::"}) {
134 next if substr($_, -2, 2) eq '::';
135 return 1 if defined &{"${name}::$_"};
136 }
137 return 0;
138}
139
fcd84ca9 1401;
141
142__END__
143
144=pod
145
146=head1 NAME
147
e522431d 148Moose - Moose, it's the new Camel
fcd84ca9 149
150=head1 SYNOPSIS
e522431d 151
152 package Point;
153 use Moose;
154
182134e8 155 has 'x' => (isa => 'Int', is => 'rw');
156 has 'y' => (isa => 'Int', is => 'rw');
e522431d 157
158 sub clear {
159 my $self = shift;
160 $self->x(0);
161 $self->y(0);
162 }
163
164 package Point3D;
165 use Moose;
166
167 extends 'Point';
09fdc1dc 168
182134e8 169 has 'z' => (isa => 'Int');
e522431d 170
171 after 'clear' => sub {
172 my $self = shift;
173 $self->{z} = 0;
174 };
175
176=head1 CAVEAT
177
178This is a B<very> early release of this module, it still needs
179some fine tuning and B<lots> more documentation. I am adopting
180the I<release early and release often> approach with this module,
181so keep an eye on your favorite CPAN mirror!
182
fcd84ca9 183=head1 DESCRIPTION
184
e522431d 185Moose is an extension of the Perl 5 object system.
186
187=head2 Another object system!?!?
fcd84ca9 188
e522431d 189Yes, I know there has been an explosion recently of new ways to
190build object's in Perl 5, most of them based on inside-out objects,
191and other such things. Moose is different because it is not a new
192object system for Perl 5, but instead an extension of the existing
193object system.
3c7278fb 194
e522431d 195Moose is built on top of L<Class::MOP>, which is a metaclass system
196for Perl 5. This means that Moose not only makes building normal
505c6fac 197Perl 5 objects better, but it also provides the power of metaclass
198programming.
e522431d 199
200=head2 What does Moose stand for??
201
202Moose doesn't stand for one thing in particular, however, if you
203want, here are a few of my favorites, feel free to contribute
204more :)
205
206=over 4
207
5569c072 208=item Make Other Object Systems Envious
e522431d 209
210=item Makes Object Orientation So Easy
211
5569c072 212=item Makes Object Orientation Spiffy- Er (sorry ingy)
505c6fac 213
5569c072 214=item Most Other Object Systems Emasculate
505c6fac 215
216=item My Overcraft Overfilled (with) Some Eels
217
218=item Moose Often Ovulate Sorta Early
219
505c6fac 220=item Many Overloaded Object Systems Exists
221
222=item Moose Offers Often Super Extensions
223
e522431d 224=back
3c7278fb 225
6ba6d68c 226=head1 BUILDING CLASSES WITH MOOSE
227
228Moose makes every attempt to provide as much convience during class
229construction/definition, but still stay out of your way if you want
230it to. Here are some of the features Moose provides:
231
232Unless specified with C<extends>, any class which uses Moose will
233inherit from L<Moose::Object>.
234
235Moose will also manage all attributes (including inherited ones) that
236are defined with C<has>. And assuming that you call C<new> which is
237inherited from L<Moose::Object>, then this includes properly initializing
238all instance slots, setting defaults where approprtiate and performing any
239type constraint checking or coercion.
240
241=head1 EXPORTED FUNCTIONS
242
243Moose will export a number of functions into the class's namespace, which
244can then be used to set up the class. These functions all work directly
245on the current class.
246
247=over 4
248
249=item B<meta>
250
251This is a method which provides access to the current class's metaclass.
252
253=item B<extends (@superclasses)>
254
255This function will set the superclass(es) for the current class.
256
257This approach is recommended instead of C<use base>, because C<use base>
258actually C<push>es onto the class's C<@ISA>, whereas C<extends> will
259replace it. This is important to ensure that classes which do not have
260superclasses properly inherit from L<Moose::Object>.
261
262=item B<has ($name, %options)>
263
264This will install an attribute of a given C<$name> into the current class.
265The list of C<%options> are the same as those provided by both
266L<Class::MOP::Attribute> and L<Moose::Meta::Attribute>, in addition to a
267few convience ones provided by Moose which are listed below:
268
269=over 4
270
076c81ed 271=item I<is =E<gt> 'rw'|'ro'>
6ba6d68c 272
273The I<is> option accepts either I<rw> (for read/write) or I<ro> (for read
274only). These will create either a read/write accessor or a read-only
275accessor respectively, using the same name as the C<$name> of the attribute.
276
277If you need more control over how your accessors are named, you can use the
278I<reader>, I<writer> and I<accessor> options inherited from L<Moose::Meta::Attribute>.
279
076c81ed 280=item I<isa =E<gt> $type_name>
6ba6d68c 281
282The I<isa> option uses Moose's type constraint facilities to set up runtime
283type checking for this attribute. Moose will perform the checks during class
284construction, and within any accessors. The C<$type_name> argument must be a
285string. The string can be either a class name, or a type defined using
286Moose's type defintion features.
287
288=back
289
076c81ed 290=item B<before $name|@names =E<gt> sub { ... }>
6ba6d68c 291
076c81ed 292=item B<after $name|@names =E<gt> sub { ... }>
6ba6d68c 293
076c81ed 294=item B<around $name|@names =E<gt> sub { ... }>
6ba6d68c 295
296This three items are syntactic sugar for the before, after and around method
297modifier features that L<Class::MOP> provides. More information on these can
298be found in the L<Class::MOP> documentation for now.
299
300=item B<confess>
301
302This is the C<Carp::confess> function, and exported here beause I use it
303all the time. This feature may change in the future, so you have been warned.
304
305=item B<blessed>
306
307This is the C<Scalar::Uti::blessed> function, it is exported here beause I
308use it all the time. It is highly recommended that this is used instead of
309C<ref> anywhere you need to test for an object's class name.
310
311=back
312
5569c072 313=head1 ACKNOWLEDGEMENTS
314
315=over 4
316
54c189df 317=item I blame Sam Vilain for introducing me to the insanity that is meta-models.
5569c072 318
54c189df 319=item I blame Audrey Tang for then encouraging my meta-model habit in #perl6.
5569c072 320
076c81ed 321=item Without Yuval "nothingmuch" Kogman this module would not be possible,
54c189df 322and it certainly wouldn't have this name ;P
5569c072 323
324=item The basis of the TypeContraints module was Rob Kinyon's idea
325originally, I just ran with it.
326
076c81ed 327=item Thanks to mst & chansen and the whole #moose poose for all the
d46a48f3 328ideas/feature-requests/encouragement
329
5569c072 330=back
331
e90c03d0 332=head1 SEE ALSO
333
334=over 4
335
6ba6d68c 336=item L<Class::MOP> documentation
337
338=item The #moose channel on irc.perl.org
339
e90c03d0 340=item L<http://forum2.org/moose/>
341
342=back
343
fcd84ca9 344=head1 BUGS
345
346All complex software has bugs lurking in it, and this module is no
347exception. If you find a bug please either email me, or add the bug
348to cpan-RT.
349
fcd84ca9 350=head1 AUTHOR
351
352Stevan Little E<lt>stevan@iinteractive.comE<gt>
353
354=head1 COPYRIGHT AND LICENSE
355
356Copyright 2006 by Infinity Interactive, Inc.
357
358L<http://www.iinteractive.com>
359
360This library is free software; you can redistribute it and/or modify
361it under the same terms as Perl itself.
362
363=cut