From: Stevan Little Date: Sat, 25 Mar 2006 19:27:34 +0000 (+0000) Subject: recipe-1 X-Git-Tag: 0_05~60 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=cdcae9704d3a6e534204e50632abd26fde5530e1;p=gitmo%2FMoose.git recipe-1 --- diff --git a/lib/Moose/Cookbook/Recipe1.pod b/lib/Moose/Cookbook/Recipe1.pod index 2c84868..b672444 100644 --- a/lib/Moose/Cookbook/Recipe1.pod +++ b/lib/Moose/Cookbook/Recipe1.pod @@ -3,7 +3,7 @@ =head1 NAME -Moose::Cookbook::Recipe1 +Moose::Cookbook::Recipe1 - The (always classic) cartesian point example. =head1 SYNOPSIS @@ -37,6 +37,188 @@ Moose::Cookbook::Recipe1 =head1 DESCRIPTION +This is the classic Point example. This one in particular I took +from the Perl 6 Apocalypse 12 document, but it is similar to the +example found in the classic K&R C book as well, and many other +places. And now, onto the code: + +As with all Perl 5 classes, a Moose class is defined in a package. +Of course we always use C and C (don't forget +that a kitten will die if you don't) and then we C. + +By loading Moose, we are enabeling the Moose "environment" to be +loaded within our package. This means that we export some functions +which serve as Moose "keywords". This is nothing fancier than that, +just plain old exported functions. + +Another important thing happens at this stage as well. Moose will +automatically set your package's superclass to be L. +The reason we do this, is so that we can be sure that you will +inherit from L and get the benefits that provides +(see the L for those details). However, you don't +actually I to inherit from L if you don't +want to, all other features of Moose are still accessible to you. + +Now, onto the keywords. The first one we see here is C, which +defines an instance attribute in your class. + + has 'x' => (isa => 'Int', is => 'ro'); + +This will create an attribute named C, it will expect that the +value stored in the attribute to pass the type constraint C (1), +and the accessor generated for this attribute will be read-only +(abbreviated as C). + +The next C line is very similar, with only one difference. + + has 'y' => (isa => 'Int', is => 'rw'); + +For the C attribute a read/write accessor will be generated +(abbreviated as C). + +At this point the attributes have been defined, and it is time to +define our methods. In Moose, as with regular Perl 5 OO, a method +is just a subroutine defined within the package. So here we create +the C method. + + sub clear { + my $self = shift; + $self->{x} = 0; + $self->y(0); + } + +It is pretty standard, the only thing to note is that we are directly +accessing the C slot in the instance L<(2)>. This is because the +value was created with a read-only accessor. This also shows that Moose +objects are not anything out of the ordinary, but just regular old +blessed HASH references. This means they are very compatible with +other Perl 5 (non-Moose) classes as well. + +The next part of the code to review is the B subclass, +B. The first item you might notice is that we do not use +the standard C declaration here. Instead we use the Moose +keyword C like so: + + extends 'Point'; + +This keyword will function very much like C does in that +it will make an attempt to load your class if it has not already been +loaded. However, it differs on one important point. The C +keyword will overwrite any previous values in your package's C<@ISA>, +where C will C values onto the package's C<@ISA>. It +is my opinion that the behavior of C is more intuitive in +that it is more explicit about defining the superclass relationship. + +A small digression here, both Moose and C support multiple +inheritence. You simply pass all the superclasses to C, +like so: + + extends 'Foo', 'Bar', 'Baz'; + +Now, back to our B class. The next thing we do is to create +a new attribute for B called C. + + has 'z' => (isa => 'Int'); + +As with B's C and C attributes, this attribute has a +type constraint of C, but it differs in that it does B +ask for any autogenerated accessors. The result being (aside from +breaking object encapsulation), that C is a private attribute. + +Next comes another Moose feature which we call method "modifiers" +(or method "advice" for the AOP inclined). The modifier used here +is the C modifier, and looks like this: + + after 'clear' => sub { + my $self = shift; + $self->{z} = 0; + }; + +This modifier tells Moose to install a C method for +B that will first run the C method for the +superclass (in this case C), and then run this +method I it (passing in the same arguments as the original +method). + +Now, of course using the C modifier is not the only way to +accomplish this. I mean, after all, this B Perl right? You +would get the same results with this code: + + sub clear { + my $self = shift; + $self->SUPER::clear(); + $self->{z} = 0; + } + +You could also use another Moose method modifier, C here, +and get the same results again. Here is how that would look. + + override 'clear' => sub { + my $self = shift; + super(); + $self->{z} = 0; + }; + +The C modifier allows you to use the C keyword +within it to dispatch to the superclass's method in a very Ruby-ish +style. + +Now of course, what use is a class if you cant instantiate objects +with it. Now since B inherits from L, it will +inherit the default L constructor called C. Here +are two examples of how that is used: + + my $point = Point->new(x => 1, y => 2); + my $point3d = Point3D->new(x => 1, y => 2, z => 3); + +As you can see, C accepts named argument pairs for any of the +attributes. It does not I that you pass in the all the +attributes, and it will politely ignore any named arguments it does +not recognize. + +From here, you can use C<$point> and C<$point3d> just as you would +any other Perl 5 object. + +=head1 CONCLUSION + +I hope this recipe has given you some explaination of how to use +Moose to build you Perl 5 classes. The next recipe will build upon +the basics shown here with more complex attributes and methods. +Please read on :) + +=head1 FOOTNOTES + +=over 4 + +=item (1) + +Several default type constraints are provided by Moose, of which +C is one. For more information on the built-in type constraints +and the type constraint system in general, see the +L documentation. + +=item (2) + +Future plans for Moose include allowing for alternate instance +structures such as blessed ARRAY refs and such. If you want you Moose +classes to be interchangable, it is advised that you avoid direct +instance access, like that which is shown above. + +=back + +=head1 SEE ALSO + +=over 4 + +=item Method Modifiers + +The concept of method modifiers is directly ripped off from CLOS. A +great explaination of them can be found by following this link. + +L + +=back + =head1 AUTHOR Stevan Little Estevan@iinteractive.comE diff --git a/lib/Moose/Cookbook/Recipe2.pod b/lib/Moose/Cookbook/Recipe2.pod index ce8ca3b..1786c1b 100644 --- a/lib/Moose/Cookbook/Recipe2.pod +++ b/lib/Moose/Cookbook/Recipe2.pod @@ -37,12 +37,12 @@ Moose::Cookbook::Recipe2 has 'overdraft_account' => (isa => 'BankAccount', is => 'rw'); before 'withdraw' => sub { - my ($self, $amount) = @_; - my $overdraft_amount = $amount - $self->balance(); - if ($overdraft_amount > 0) { - $self->overdraft_account->withdraw($overdraft_amount); - $self->deposit($overdraft_amount); - } + my ($self, $amount) = @_; + my $overdraft_amount = $amount - $self->balance(); + if ($overdraft_amount > 0) { + $self->overdraft_account->withdraw($overdraft_amount); + $self->deposit($overdraft_amount); + } }; =head1 DESCRIPTION