inherited-slot-specifications
[gitmo/Moose.git] / lib / Moose.pm
CommitLineData
fcd84ca9 1
2package Moose;
3
4use strict;
5use warnings;
6
2d562421 7our $VERSION = '0.05';
fcd84ca9 8
cc65ead0 9use Scalar::Util 'blessed', 'reftype';
fcd84ca9 10use Carp 'confess';
bc1e29b5 11use Sub::Name 'subname';
fcd84ca9 12
7f18097c 13use UNIVERSAL::require;
2d562421 14use Sub::Exporter;
7f18097c 15
ef1d5f4b 16use Class::MOP;
17
c0e30cf5 18use Moose::Meta::Class;
7415b2cb 19use Moose::Meta::TypeConstraint;
7c13858b 20use Moose::Meta::TypeCoercion;
78cd1d3b 21use Moose::Meta::Attribute;
c0e30cf5 22
fcd84ca9 23use Moose::Object;
7415b2cb 24use Moose::Util::TypeConstraints;
a15dff8d 25
a3c7e2fe 26{
27 my ( $CALLER, %METAS );
28
2d562421 29 sub _find_meta {
a3c7e2fe 30 my $class = $CALLER;
31
32 return $METAS{$class} if exists $METAS{$class};
33
34 # make a subtype for each Moose class
35 subtype $class
36 => as 'Object'
37 => where { $_->isa($class) }
38 unless find_type_constraint($class);
39
40 my $meta;
41 if ($class->can('meta')) {
42 $meta = $class->meta();
43 (blessed($meta) && $meta->isa('Moose::Meta::Class'))
44 || confess "Whoops, not møøsey enough";
45 }
46 else {
590868a3 47 $meta = Moose::Meta::Class->initialize($class);
a3c7e2fe 48 $meta->add_method('meta' => sub {
49 # re-initialize so it inherits properly
590868a3 50 Moose::Meta::Class->initialize($class);
a3c7e2fe 51 })
52 }
53
54 # make sure they inherit from Moose::Object
55 $meta->superclasses('Moose::Object')
56 unless $meta->superclasses();
57
58 return $METAS{$class} = $meta;
59 }
60
61 my %exports = (
62 extends => sub {
2d562421 63 my $meta = _find_meta();
3d544ed5 64 return subname 'Moose::extends' => sub {
a3c7e2fe 65 _load_all_classes(@_);
66 $meta->superclasses(@_)
67 };
68 },
69 with => sub {
2d562421 70 my $meta = _find_meta();
3d544ed5 71 return subname 'Moose::with' => sub {
a3c7e2fe 72 my ($role) = @_;
73 _load_all_classes($role);
74 $role->meta->apply($meta);
75 };
76 },
77 has => sub {
2d562421 78 my $meta = _find_meta();
3d544ed5 79 return subname 'Moose::has' => sub {
a3c7e2fe 80 my ($name, %options) = @_;
2d2b92e5 81 if ($name =~ /^\+(.*)/) {
1d768fb1 82 my $inherited_attr = $meta->find_attribute_by_name($1);
83 (defined $inherited_attr)
84 || confess "Could not find an attribute by the name of '$1' to inherit from";
85 (scalar keys %options == 1 && exists $options{default})
86 || confess "Inherited slot specifications can only alter the 'default' option";
87 my $new_attr = $inherited_attr->clone(%options);
88 $meta->add_attribute($new_attr);
b0ea39ef 89 }
90 else {
2d2b92e5 91 if ($options{metaclass}) {
92 _load_all_classes($options{metaclass});
93 $meta->add_attribute($options{metaclass}->new($name, %options));
94 }
95 else {
96 $meta->add_attribute($name, %options);
97 }
b0ea39ef 98 }
a3c7e2fe 99 };
100 },
101 before => sub {
2d562421 102 my $meta = _find_meta();
3d544ed5 103 return subname 'Moose::before' => sub {
a3c7e2fe 104 my $code = pop @_;
105 $meta->add_before_method_modifier($_, $code) for @_;
106 };
107 },
108 after => sub {
2d562421 109 my $meta = _find_meta();
3d544ed5 110 return subname 'Moose::after' => sub {
a3c7e2fe 111 my $code = pop @_;
112 $meta->add_after_method_modifier($_, $code) for @_;
113 };
114 },
115 around => sub {
2d562421 116 my $meta = _find_meta();
3d544ed5 117 return subname 'Moose::around' => sub {
a3c7e2fe 118 my $code = pop @_;
119 $meta->add_around_method_modifier($_, $code) for @_;
120 };
121 },
122 super => sub {
2d562421 123 my $meta = _find_meta();
3d544ed5 124 return subname 'Moose::super' => sub {};
a3c7e2fe 125 },
126 override => sub {
2d562421 127 my $meta = _find_meta();
3d544ed5 128 return subname 'Moose::override' => sub {
a3c7e2fe 129 my ($name, $method) = @_;
130 $meta->add_override_method_modifier($name => $method);
131 };
132 },
133 inner => sub {
2d562421 134 my $meta = _find_meta();
3d544ed5 135 return subname 'Moose::inner' => sub {};
a3c7e2fe 136 },
137 augment => sub {
2d562421 138 my $meta = _find_meta();
3d544ed5 139 return subname 'Moose::augment' => sub {
a3c7e2fe 140 my ($name, $method) = @_;
141 $meta->add_augment_method_modifier($name => $method);
142 };
143 },
144 confess => sub {
145 return \&Carp::confess;
146 },
147 blessed => sub {
148 return \&Scalar::Util::blessed;
149 }
150 );
3d544ed5 151
a3c7e2fe 152 my $exporter = Sub::Exporter::build_exporter({
153 exports => \%exports,
154 groups => {
155 default => [':all']
156 }
157 });
158
159 sub import {
160 $CALLER = caller();
161
162 # we should never export to main
163 return if $CALLER eq 'main';
164
165 goto $exporter;
166 };
fcd84ca9 167}
168
e9bb8a31 169## Utility functions
170
78cd1d3b 171sub _load_all_classes {
e9bb8a31 172 foreach my $super (@_) {
173 # see if this is already
174 # loaded in the symbol table
175 next if _is_class_already_loaded($super);
176 # otherwise require it ...
177 ($super->require)
178 || confess "Could not load superclass '$super' because : " . $UNIVERSAL::require::ERROR;
179 }
180}
181
d7f17ebb 182sub _is_class_already_loaded {
183 my $name = shift;
184 no strict 'refs';
185 return 1 if defined ${"${name}::VERSION"} || defined @{"${name}::ISA"};
186 foreach (keys %{"${name}::"}) {
187 next if substr($_, -2, 2) eq '::';
188 return 1 if defined &{"${name}::$_"};
189 }
190 return 0;
191}
192
fcd84ca9 1931;
194
195__END__
196
197=pod
198
199=head1 NAME
200
e522431d 201Moose - Moose, it's the new Camel
fcd84ca9 202
203=head1 SYNOPSIS
e522431d 204
205 package Point;
206 use Moose;
207
182134e8 208 has 'x' => (isa => 'Int', is => 'rw');
209 has 'y' => (isa => 'Int', is => 'rw');
e522431d 210
211 sub clear {
212 my $self = shift;
213 $self->x(0);
214 $self->y(0);
215 }
216
217 package Point3D;
218 use Moose;
219
220 extends 'Point';
09fdc1dc 221
182134e8 222 has 'z' => (isa => 'Int');
e522431d 223
224 after 'clear' => sub {
225 my $self = shift;
226 $self->{z} = 0;
227 };
228
229=head1 CAVEAT
230
79592a54 231This is an early release of this module, it still needs
e522431d 232some fine tuning and B<lots> more documentation. I am adopting
233the I<release early and release often> approach with this module,
234so keep an eye on your favorite CPAN mirror!
235
fcd84ca9 236=head1 DESCRIPTION
237
e522431d 238Moose is an extension of the Perl 5 object system.
239
240=head2 Another object system!?!?
fcd84ca9 241
e522431d 242Yes, I know there has been an explosion recently of new ways to
243build object's in Perl 5, most of them based on inside-out objects,
244and other such things. Moose is different because it is not a new
245object system for Perl 5, but instead an extension of the existing
246object system.
3c7278fb 247
e522431d 248Moose is built on top of L<Class::MOP>, which is a metaclass system
249for Perl 5. This means that Moose not only makes building normal
505c6fac 250Perl 5 objects better, but it also provides the power of metaclass
251programming.
e522431d 252
253=head2 What does Moose stand for??
254
255Moose doesn't stand for one thing in particular, however, if you
256want, here are a few of my favorites, feel free to contribute
257more :)
258
259=over 4
260
5569c072 261=item Make Other Object Systems Envious
e522431d 262
263=item Makes Object Orientation So Easy
264
5569c072 265=item Makes Object Orientation Spiffy- Er (sorry ingy)
505c6fac 266
5569c072 267=item Most Other Object Systems Emasculate
505c6fac 268
269=item My Overcraft Overfilled (with) Some Eels
270
271=item Moose Often Ovulate Sorta Early
272
505c6fac 273=item Many Overloaded Object Systems Exists
274
275=item Moose Offers Often Super Extensions
276
446e850f 277=item Meta Object Orientation Syntax Extensions
278
e522431d 279=back
3c7278fb 280
6ba6d68c 281=head1 BUILDING CLASSES WITH MOOSE
282
283Moose makes every attempt to provide as much convience during class
284construction/definition, but still stay out of your way if you want
285it to. Here are some of the features Moose provides:
286
287Unless specified with C<extends>, any class which uses Moose will
288inherit from L<Moose::Object>.
289
290Moose will also manage all attributes (including inherited ones) that
291are defined with C<has>. And assuming that you call C<new> which is
292inherited from L<Moose::Object>, then this includes properly initializing
293all instance slots, setting defaults where approprtiate and performing any
294type constraint checking or coercion.
295
79592a54 296For more details, see the ever expanding L<Moose::Cookbook>.
297
6ba6d68c 298=head1 EXPORTED FUNCTIONS
299
300Moose will export a number of functions into the class's namespace, which
301can then be used to set up the class. These functions all work directly
302on the current class.
303
304=over 4
305
306=item B<meta>
307
308This is a method which provides access to the current class's metaclass.
309
310=item B<extends (@superclasses)>
311
312This function will set the superclass(es) for the current class.
313
314This approach is recommended instead of C<use base>, because C<use base>
315actually C<push>es onto the class's C<@ISA>, whereas C<extends> will
316replace it. This is important to ensure that classes which do not have
317superclasses properly inherit from L<Moose::Object>.
318
e9ec68d6 319=item B<with ($role)>
320
76d37e5a 321This will apply a given C<$role> to the local class. Role support is
322currently very experimental, see L<Moose::Role> for more details.
e9ec68d6 323
6ba6d68c 324=item B<has ($name, %options)>
325
326This will install an attribute of a given C<$name> into the current class.
327The list of C<%options> are the same as those provided by both
328L<Class::MOP::Attribute> and L<Moose::Meta::Attribute>, in addition to a
329few convience ones provided by Moose which are listed below:
330
331=over 4
332
076c81ed 333=item I<is =E<gt> 'rw'|'ro'>
6ba6d68c 334
335The I<is> option accepts either I<rw> (for read/write) or I<ro> (for read
336only). These will create either a read/write accessor or a read-only
337accessor respectively, using the same name as the C<$name> of the attribute.
338
339If you need more control over how your accessors are named, you can use the
340I<reader>, I<writer> and I<accessor> options inherited from L<Moose::Meta::Attribute>.
341
076c81ed 342=item I<isa =E<gt> $type_name>
6ba6d68c 343
344The I<isa> option uses Moose's type constraint facilities to set up runtime
345type checking for this attribute. Moose will perform the checks during class
346construction, and within any accessors. The C<$type_name> argument must be a
347string. The string can be either a class name, or a type defined using
348Moose's type defintion features.
349
350=back
351
076c81ed 352=item B<before $name|@names =E<gt> sub { ... }>
6ba6d68c 353
076c81ed 354=item B<after $name|@names =E<gt> sub { ... }>
6ba6d68c 355
076c81ed 356=item B<around $name|@names =E<gt> sub { ... }>
6ba6d68c 357
358This three items are syntactic sugar for the before, after and around method
359modifier features that L<Class::MOP> provides. More information on these can
360be found in the L<Class::MOP> documentation for now.
361
159da176 362=item B<super>
363
364The keyword C<super> is a noop when called outside of an C<override> method. In
365the context of an C<override> method, it will call the next most appropriate
366superclass method with the same arguments as the original method.
367
368=item B<override ($name, &sub)>
369
370An C<override> method, is a way of explictly saying "I am overriding this
371method from my superclass". You can call C<super> within this method, and
372it will work as expected. The same thing I<can> be accomplished with a normal
373method call and the C<SUPER::> pseudo-package, it is really your choice.
374
375=item B<inner>
376
377The keyword C<inner>, much like C<super>, is a no-op outside of the context of
378an C<augment> method. You can think of C<inner> as being the inverse of
379C<super>, the details of how C<inner> and C<augment> work is best described in
380the L<Moose::Cookbook>.
381
382=item B<augment ($name, &sub)>
383
384An C<augment> method, is a way of explictly saying "I am augmenting this
385method from my superclass". Once again, the details of how C<inner> and
386C<augment> work is best described in the L<Moose::Cookbook>.
387
6ba6d68c 388=item B<confess>
389
390This is the C<Carp::confess> function, and exported here beause I use it
391all the time. This feature may change in the future, so you have been warned.
392
393=item B<blessed>
394
395This is the C<Scalar::Uti::blessed> function, it is exported here beause I
396use it all the time. It is highly recommended that this is used instead of
397C<ref> anywhere you need to test for an object's class name.
398
399=back
400
05d9eaf6 401=head1 CAVEATS
402
403=over 4
404
405=item *
406
407It should be noted that C<super> and C<inner> can B<not> be used in the same
408method. However, they can be combined together with the same class hierarchy,
409see F<t/014_override_augment_inner_super.t> for an example.
410
411The reason that this is so is because C<super> is only valid within a method
412with the C<override> modifier, and C<inner> will never be valid within an
413C<override> method. In fact, C<augment> will skip over any C<override> methods
414when searching for it's appropriate C<inner>.
415
416This might seem like a restriction, but I am of the opinion that keeping these
417two features seperate (but interoperable) actually makes them easy to use since
418their behavior is then easier to predict. Time will tell if I am right or not.
419
420=back
421
5569c072 422=head1 ACKNOWLEDGEMENTS
423
424=over 4
425
54c189df 426=item I blame Sam Vilain for introducing me to the insanity that is meta-models.
5569c072 427
54c189df 428=item I blame Audrey Tang for then encouraging my meta-model habit in #perl6.
5569c072 429
076c81ed 430=item Without Yuval "nothingmuch" Kogman this module would not be possible,
54c189df 431and it certainly wouldn't have this name ;P
5569c072 432
433=item The basis of the TypeContraints module was Rob Kinyon's idea
434originally, I just ran with it.
435
076c81ed 436=item Thanks to mst & chansen and the whole #moose poose for all the
d46a48f3 437ideas/feature-requests/encouragement
438
5569c072 439=back
440
e90c03d0 441=head1 SEE ALSO
442
443=over 4
444
6ba6d68c 445=item L<Class::MOP> documentation
446
447=item The #moose channel on irc.perl.org
448
e90c03d0 449=item L<http://forum2.org/moose/>
450
159da176 451=item L<http://www.cs.utah.edu/plt/publications/oopsla04-gff.pdf>
452
453This paper (suggested by lbr on #moose) was what lead to the implementation
454of the C<super>/C<overrride> and C<inner>/C<augment> features. If you really
455want to understand this feature, I suggest you read this.
456
e90c03d0 457=back
458
fcd84ca9 459=head1 BUGS
460
461All complex software has bugs lurking in it, and this module is no
462exception. If you find a bug please either email me, or add the bug
463to cpan-RT.
464
fcd84ca9 465=head1 AUTHOR
466
467Stevan Little E<lt>stevan@iinteractive.comE<gt>
468
469=head1 COPYRIGHT AND LICENSE
470
471Copyright 2006 by Infinity Interactive, Inc.
472
473L<http://www.iinteractive.com>
474
475This library is free software; you can redistribute it and/or modify
476it under the same terms as Perl itself.
477
478=cut