The methods associated with a file might include C<rename()> and
C<write()>.
-In Perl most objects are hash references, but the OO systems we
-recommend keep you from having to worry about this. In practice, it's
-best to consider an object's internal data structure opaque.
+In Perl most objects are hashes, but the OO systems we recommend keep
+you from having to worry about this. In practice, it's best to consider
+an object's internal data structure opaque.
=head2 Class
=head3 Blessing
-As we said earlier, most Perl objects are hash references, but an
-object can be a reference to any Perl data type (scalar, array, etc.).
-Turning a plain reference into an object is done by B<blessing> that
-reference using Perl's C<bless> function.
+As we said earlier, most Perl objects are hashes, but an object can be
+an instance of any Perl data type (scalar, array, etc.). Turning a
+plain data structure into an object is done by B<blessing> that data
+structure using Perl's C<bless> function.
While we strongly suggest you don't build your objects from scratch,
-you should know the term B<bless>. A B<blessed> reference is an object.
-We sometimes say that an object has been "blessed into a class".
+you should know the term B<bless>. A B<blessed> data structure (aka "a
+referent") is an object. We sometimes say that an object has been
+"blessed into a class".
-Once a reference has been blessed, the C<blessed> function from the
+Once a referent has been blessed, the C<blessed> function from the
L<Scalar::Util> core module can tell us its class name. This subroutine
returns an object's class when passed an object, and false otherwise.
=head2 Methods
You already learned that a B<method> is a subroutine that operates on
-an object's data. You can think of a method as the things that an
-object can I<do>.
+an object. You can think of a method as the things that an object can
+I<do>. If an object is a noun, then methods are its verbs (save, print,
+open).
In Perl, methods are simply subroutines that live in a class's package.
Methods are always written to receive the object as their first
print "This file is at ", $self->path, "\n";
}
- $larry->print_path;
+ $file->print_info;
# The file is at /etc/hostname
What makes a method special is I<how it's called>. The arrow operator
print $prefix, ", ", $self->path, "\n";
}
- $larry->print_info("The file is located at ");
+ $file->print_info("The file is located at ");
# The file is located at /etc/hostname
=head2 Attributes
has a path. Attributes are sometimes called B<properties>.
Perl has no special syntax for attributes. Under the hood, attributes
-are often stored as keys in the object's hash reference, but don't
+are often stored as keys in the object's underlying hash, but don't
worry about this.
We recommend that you only access attributes via B<accessor> methods.
You might also see the terms B<getter> and B<setter>. These are two
types of accessors. A getter gets the attribute's value, while a setter
-sets it.
+sets it. Another term for a setter is B<mutator>
Attributes are typically defined as read-only or read-write. Read-only
attributes can only be set when the object is first created, while
B<Polymorphism> is a fancy way of saying that objects from two
different classes share an API. For example, we could have C<File> and
C<WebPage> classes which both have a C<print_content()> method. This
-method might produce different output for each class, but the basic API
-is the same.
+method might produce different output for each class, but they share a
+common interface.
While the two classes may differ in many ways, when it comes to the
C<print_content()> method, they are the same. This means that we can
=head2 Inheritance
-B<Inheritance> is a way to specialize an existing class. It allows one
-class to reuse the methods and attributes of another class.
+B<Inheritance> lets you create a specialized version of an existing
+class. Inheritance lets the new class reuse the methods and attributes of
+another class.
-We often refer to inheritance relationships as B<parent-child> or
-C<superclass/subclass> relationships. Sometimes we say that the child
-has an B<is-a> relationship with its parent class.
-
-Inheritance is best used to create a specialized version of a class.
For example, we could create an C<File::MP3> class which B<inherits>
from C<File>. An C<File::MP3> B<is-a> I<more specific> type of C<File>.
All mp3 files are files, but not all files are mp3 files.
+We often refer to inheritance relationships as B<parent-child> or
+C<superclass/subclass> relationships. Sometimes we say that the child
+has an B<is-a> relationship with its parent class.
+
C<File> is a B<superclass> of C<File::MP3>, and C<File::MP3> is a
B<subclass> of C<File>.
Perl allows multiple inheritance, which means that a class can inherit
from multiple parents. While this is possible, we strongly recommend
against it. Generally, you can use B<roles> to do everything you can do
-with multiple inheritance in a cleaner way.
+with multiple inheritance, but in a cleaner way.
Note that there's nothing wrong with defining multiple subclasses of a
given class. This is both common and safe. For example, we might define
violating encapsulation, but a good API can minimize the need to do
this.
-We mentioned earlier that most Perl objects are implemented as hash
-references under the hood. The principle of encapsulation tells us that
-we should not rely on this. Instead, we should use accessor methods to
-access the data in that hash reference. The object systems that we
-recommend below all automate the generation of accessor methods. If you
-use one of them, you should never have to access the object as a hash
-reference directly.
+We mentioned earlier that most Perl objects are implemented as hashes
+under the hood. The principle of encapsulation tells us that we should
+not rely on this. Instead, we should use accessor methods to access the
+data in that hash. The object systems that we recommend below all
+automate the generation of accessor methods. If you use one of them,
+you should never have to access the object as a hash directly.
=head2 Composition
=over 4
-=item
+=item *
The system being designed is large, or is likely to become large.
-=item
+=item *
The data can be aggregated into obvious structures, especially if
there's a large amount of data in each aggregate.
-=item
+=item *
The various types of data aggregate form a natural hierarchy that
facilitates the use of inheritance and polymorphism.
-=item
+=item *
You have a piece of data on which many different operations are
applied.
-=item
+=item *
You need to perform the same general operations on related types of
data, but with slight variations depending on the specific type of data
the operations are applied to.
-=item
+=item *
It's likely you'll have to add new data types later.
-=item
+=item *
The typical interactions between pieces of data are best represented by
operators.
-=item
+=item *
The implementation of individual components of the system is likely to
change over time.
-=item
+=item *
The system design is already object-oriented.
-=item
+=item *
Large numbers of other programmers will be using your code modules.
Here is our C<File> class using C<Moose>:
-
-Here's a simple but complete C<Moose> class:
-
package File;
use Moose;
compiler, or if having I<any> dependencies is a problem, then C<Moose>
may not be right for you.
-=head3 Mouse
+=head3 Moo
If you try C<Moose> and find that one of these issues is preventing you
-from using C<Moose>, we encourage you to consider L<Mouse> next.
-C<Mouse> implements a subset of C<Moose>'s functionality in a simpler
-package. For all features that it does implement, the end-user API is
-I<identical> to C<Moose>, meaning you can switch from C<Mouse> to
+from using C<Moose>, we encourage you to consider L<Moo> next.
+C<Moo> implements a subset of C<Moose>'s functionality in a simpler
+package. For most features that it does implement, the end-user API is
+I<identical> to C<Moose>, meaning you can switch from C<Moo> to
C<Moose> quite easily.
-C<Mouse> does not implement most of C<Moose>'s introspection API, so
-it's often faster when loading your modules. Additionally, it has no
-I<required> non-core dependencies and can run without a compiler. If
-you do have a compiler, C<Mouse> will use it to compile some of its
-code for a speed boost.
-
-Finally, it ships with a C<C<Mouse>::Tiny> module that takes most of
-C<Mouse>'s features and bundles them up in a single module file. You
-can copy this module file into your application's library directory for
-easy bundling.
+C<Moo> does not implement most of C<Moose>'s introspection API, so it's often
+faster when loading your modules. Additionally, none of its dependencies
+require XS, so it can be installed on machines without a compiler.
-The C<Moose> authors hope that one day C<Mouse> can be made obsolete by
+The C<Moose> authors hope that one day C<Moo> can be made obsolete by
improving C<Moose> enough, but for now it provides a worthwhile
alternative to C<Moose>.
=item * L<Moose>
C<Moose> is the maximal option. It has a lot of features, a big
-ecosystem, and a thriving user base. We also covered L<Mouse> briefly.
-C<Mouse> is C<Moose> lite, and a reasonable alternative when Moose
+ecosystem, and a thriving user base. We also covered L<Moo> briefly.
+C<Moo> is C<Moose> lite, and a reasonable alternative when Moose
doesn't work for your application.
=item * L<Class::Accessor>
=head1 CONCLUSION
-As we said before, Perl's minimal OO system has lead to a flourishing
-of OO systems on CPAN. While you can still drop down to the bare metal
-and write your classes by hand, there's really no reason to do that in
-2011.
+As we said before, Perl's minimal OO system has led to a profusion of
+OO systems on CPAN. While you can still drop down to the bare metal and
+write your classes by hand, there's really no reason to do that with
+modern Perl.
For small systems, L<Object::Tiny> and L<Class::Accessor> both provide
minimal object systems that take care of basic boilerplate for you.