
=pod

=head1 NAME

Moose::Cookbook::Snack::Perl5ObjsVsMooseObjs - Short comparison between Perl 5
objects and Moose objects

=head1 SYNOPSIS

    package Moose::Demo;
    use Moose; # automagically sets 'strict' and 'warnings'

    has 'script_name' => ( is => 'rw', required => 1);

    package main;
    
    # '$0' is the name of this script, set automatically by Perl
    my $demo = Moose::Demo->new( script_name => $0 );

    print "My name is " . $demo->script_name . "\n";
    print "I am a " . $demo->meta->name . " type of object\n";

=head1 DESCRIPTION

So what's the big stink about Moose?  Perl 5 comes with objects and object
oriented programming already.  Given the above Moose code, what would similar
code look like in the existing Perl 5 object-oriented style of programming?
Let's take a look and find out...

=head2 Perl 5 OO Example

    # Perl 5 Object, as taught by the 'perltoot' POD page
    package Perl5::Demo;
    use strict;
    use warnings;

    
    sub new {
        my $class = shift;
        # assign the rest of the method arguments to a temp hash
        my %args = @_;

        # create the object out of a blessed hash reference
        my $self = bless ( {}, ref($class) || $class );
        # create the script_name attribute
        $self->{script_name} = undef;

        # verify that the user passed in the 'script_name' attribute
        if ( exists $args{script_name} ) {
            $self->script_name($args{script_name});
        } 
        else {
            die "ERROR: can't create object without 'script_name' ";
        }

        # return the object reference back to the caller
        return $self;
    }
    
    sub script_name {
        my $self = shift;
        # check for arguments; use the argument 
        # if passed in, otherwise return the 
        # existing value (if any)
        if (@_) { 
            $self->{script_name} = shift;
        }
        return $self->{script_name};
    }

    package main;
    use strict;
    use warnings;

    my $demo = Perl5::Demo->new( script_name => $0 );

    print "My name is " . $demo->script_name . "\n";
    print "I am a " . ref($demo) . " type of object\n";

Looks more complex, right?  Moose does a lot of the labor when working with
Perl objects, so that you don't have to.  What are some of the specific
differences between Moose and Perl 5 Objects?

=head3 Difference #1 - declaration of object attributes

Both the Moose and Perl 5 objects have one attribute, C<script_name>.  It's a
good programming practice to always validate user input, so we have the Perl 5
object check to make sure that the user passes in the C<script_name> attribute
to it when the object is created.  The Moose object automatically checks this
for us when we set C<required =E<gt> 1> in the C<has> function for the Moose
object.

In more advanced Moose usage, you can use something called 'type constraints'
when creating your Moose objects.  Type constraints are used to validate what
the user passes in when setting Moose object attributes.  If the user passes
in a type of data that Moose is not expecting, then the type constraints in
Moose (specifically, the L<Moose::Util::TypeConstraint> module) will let the
user know this in no uncertain terms.  Type constraints in Moose can be as
simple as strings or numbers, or as complex as other Moose objects.

=head3 Difference #2 - strict and warning pragmas

Moose sets the 'strict' and 'warnings' pragmas for you automatically.  We have
to do this for ourselves in the Perl 5 example.

=head3 Difference #3 - Determining an object's class name

The C<ref()> function in Perl 5 is how you determine an object's class name.
The proper way to do this with Moose is C<$object-E<gt>meta-E<gt>name>;
    
    # an object's class name in Perl 5 OO
    print "I am a " . ref($demo) . " type of object\n";

    # an object's class name in Moose
    print "I am a " . $demo->meta->name . " type of object\n";

Moose builds on C<Class::MOP> to provide a rich introspection API that
goes way beyond just getting the class name. Check out the
C<Class::MOP> documentation for more details.

=head3 Difference #4 - Assigning values to Moose object attributes

When you wish to assign a value directly to an object attribute for a Perl 5
object, you can either create an object method that handles the value for you;

    package Perl5Object;
    sub set_x { # some code here that sets 'x' }
    package main;
    # later on...
    $self->set_x(0);

or you can assign the value directly to the Perl 5 object attribute like this:

    $self->{x} = 0; 

Moose creates object methods for handling attributes for you, as long as you
specified C<is =E<gt> rw> for each C<has> statement inside the object
declaration.  This is mentioned in L<Moose::Cookbook::WTF>, in the section
labeld B<Accessors>, but briefly:

    package MooseObject;
    has 'x' => (is => 'rw');
    package main; 
    # later on...
    $self->x(0);    

The syntax shown for the Perl 5 object (C<$self-E<gt>{x} = 0>) will
also work on the Moose object, as Moose objects are, by default,
blessed hashes just like the average Perl object is.  However, if you
access the object's hash reference directly via the latter syntax you
will have several problems.

First, Moose will no longer be able to enforce attribute constraints,
such as read-only or type constraints. Second, you've broken that
object's encapsulation, and encapsulation is one of the reasons you
want to use objects in the first place, right?

=head1 SEE ALSO

=over 4

=item L<Moose::Cookbook::Recipe1> - The 'Point' object example

=item L<Moose::Util::TypeConstraints> - Type constraints that Moose can use
and the tools to extend them or create your own.

=item L<Moose::Cookbook::WTF> - For when things go wrong with Moose

=back

=head1 AUTHOR

Brian Manning <elspicyjack at gmail dot com>

=head1 COPYRIGHT AND LICENSE

Copyright 2006-2008 by Infinity Interactive, Inc.

L<http://www.iinteractive.com>

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut
