summaryrefslogtreecommitdiff
path: root/pod/perlootut.pod
diff options
context:
space:
mode:
authorDave Rolsky <autarch@urth.org>2011-07-07 11:36:37 -0500
committerDave Rolsky <autarch@urth.org>2011-09-08 21:47:22 -0500
commitdbfe29416ae22f393039d7e661b8a11632e590a0 (patch)
treedc29adb51c80e4f6786bf6a37f4d0ced0219ac6e /pod/perlootut.pod
parent935647290357b277a54366c3caf2ddc89bfbd3eb (diff)
downloadperl-dbfe29416ae22f393039d7e661b8a11632e590a0.tar.gz
Check in new OO tutorial - perlootut
Diffstat (limited to 'pod/perlootut.pod')
-rw-r--r--pod/perlootut.pod677
1 files changed, 677 insertions, 0 deletions
diff --git a/pod/perlootut.pod b/pod/perlootut.pod
new file mode 100644
index 0000000000..e1cfedbbca
--- /dev/null
+++ b/pod/perlootut.pod
@@ -0,0 +1,677 @@
+=encoding utf8
+
+=for comment
+Consistent formatting of this file is achieved with:
+ perl ./Porting/podtidy pod/perlootut.pod
+
+=head1 NAME
+
+perlootut - Object-Oriented Programming in Perl Tutorial
+
+=head1 DATE
+
+This document was created in February, 2011.
+
+=head1 DESCRIPTION
+
+This document provides an introduction to object-oriented programming
+in Perl. It begins with a brief overview of the concepts behind object
+oriented design. Then it introduces several different OO systems from
+L<CPAN|http://search.cpan.org> which build on top of what Perl
+provides.
+
+By default, Perl's built-in OO system is very minimal, leaving you to
+do most of the work. This minimalism made a lot of sense in 1994, but
+in the years since Perl 5.0 we've seen a number of common patterns
+emerge in Perl OO. Fortunately, Perl's flexibility has allowed a rich
+ecosystem of Perl OO systems to flourish.
+
+If you want to know how Perl OO works under the hood, the L<perlobj>
+document explains the nitty gritty details.
+
+This document assumes that you already understand the basics of Perl
+syntax, variable types, operators, and subroutine calls. If you don't
+understand these concepts yet, please read L<perlintro> first. You
+should also read the L<perlsyn>, L<perlop>, and L<perlsub> documents.
+
+=head1 OBJECT-ORIENTED FUNDAMENTALS
+
+Most object systems share a number of common concepts. You've probably
+heard terms like "class", "object, "method", and "attribute" before.
+Understanding the concepts will make it much easier to read and write
+object-oriented code. If you're already familiar with these terms, you
+should still skim this section, since it explains each concept in terms
+of Perl's OO implementation.
+
+Perl's OO system is class-based. Class-based OO is fairly common. It's
+used by Java, C++, C#, Python, Ruby, and many other languages. There
+are other object orientation paradigms as well. JavaScript is the most
+popular language to use another paradigm. JavaScript's OO system is
+prototype-based.
+
+=head2 Object
+
+An B<object> is a data structure that bundles together data and
+subroutines which operate on that data. An object's data is called
+B<attributes>, and its subroutines are called B<methods>. An object can
+be thought of as a noun (a person, a web service, a computer).
+
+An object represents a single discrete thing. For example, an
+object might represent a person. The attributes for a person object
+might include name, birth date, and country of residence. If we created
+an object to represent Larry Wall, Perl's creator, that object's name
+would be "Larry Wall", born on "September 27, 1954", and living in
+"USA".
+
+The methods associated with a person might include C<print_greeting()>
+and C<calculate_age()>.
+
+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.
+
+=head2 Class
+
+A B<class> defines the behavior of a category of objects. A class is a
+name for a category (like "Person"), and a class also defines the
+behavior of objects in that category.
+
+All objects belong to a specific class. For example, our Larry Wall
+object belongs to the C<Person> class. When we want to create a
+specific object, we start with its class, and B<construct> or
+B<instantiate> an object. A specific object is often referred to as an
+B<instance> of a class.
+
+In Perl, any package can be a class. The difference between a package
+which is a class and one which isn't is based on how the package is
+used. Here's our "class declaration" for the Person class:
+
+ package Person;
+
+In Perl, there is no special keyword for constructing an object.
+However, most OO modules on CPAN use a method named C<new()> to
+construct a new object:
+
+ my $larry = Person->new(
+ name => 'Larry Wall',
+ birth_date => '1954-09-27',
+ country_code => 'us',
+ );
+
+(Don't worry about that C<< -> >> operator, it will be explained
+later.)
+
+=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.
+
+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".
+
+Once a reference 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.
+
+ use Scalar::Util 'blessed';
+
+ print blessed($hash); # undef
+ print blessed($larry); # Person
+
+=head3 Constructor
+
+A B<constructor> creates a new object. In Perl, a class's constructor
+is just another method, unlike some other languages, which provide
+syntax for constructors. Most Perl classes use C<new> as the name for
+their constructor:
+
+ my $file = File->new();
+
+=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>.
+
+In Perl, methods are simply subroutines that live in a class's package.
+Methods are always written to receive the object as their first
+argument:
+
+ sub print_greeting {
+ my $self = shift;
+
+ print "Hello, ", $self->name, "\n";
+ }
+
+ $larry->print_greeting; # Hello, Larry Wall
+
+What makes a method special is I<how it's called>. The arrow operator
+(C<< -> >>) tells Perl that we are calling a method.
+
+When we make a method call, Perl arranges for the method's B<invocant>
+to be passed as the first argument. B<Invocant> is a fancy name for the
+thing on the left side of the arrow. The invocant can either be a class
+name or an object. We can also pass additional arguments to the method:
+
+ sub print_greeting {
+ my $self = shift;
+ my $greeting = shift // "Hello";
+
+ print $greeting, ", ", $self->name, "\n";
+ }
+
+ $larry->print_greeting("Yo, Wassup"); # Yo, Wassup, Larry Wall
+
+=head2 Attributes
+
+Each class can define its B<attributes>. When we instantiate an object,
+we assign values to those attributes. For example, every C<Person>
+object has a name. 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
+worry about this.
+
+We recommend that you only access attributes via B<accessor> methods.
+These are methods that can get or set the value of each attribute. We
+saw this earlier in the C<print_greeting()> example, which calls C<<
+$self->name >>.
+
+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.
+
+Attributes are typically defined as read-only or read-write. Read-only
+attributes can only be set when the object is first created, while
+read-write attributes can be altered at any time.
+
+The value of an attribute may itself be another object. For example,
+instead of returning its birth date as a string, the C<Person> class
+could return a L<DateTime> object representing that date.
+
+It's possible to have a class that does not expose any publicly
+settable attributes. Not every class has attributes and methods.
+
+=head2 Polymorphism
+
+B<Polymorphism> is a fancy way of saying that objects from two
+different classes share an API. For example, we could have C<Person>
+and C<Animal> classes which both have a C<speak()> method. This method
+might produce different output for each class, but the basic API is the
+same.
+
+While the two classes may differ in many ways, when it comes to the
+C<speak()> method, they are the same. This means that we can try to
+call the C<speak()> method on an object of either class, and B<we don't
+have to know what class the object belongs to!>
+
+Polymorphism is one of the key concepts of object-oriented design.
+
+=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.
+
+We often refer to inheritance relationships as B<parent-child> or
+C<superclass/subclass> relationships. Sometimes this is called an
+B<is-a> relationship.
+
+Inheritance is best used to create a specialized version of a class.
+For example, we could create an C<Employee> class which B<inherits>
+from C<Person>. An C<Employee> B<is-a> I<more specific> type of
+C<Person>. All employees are persons, but not all persons are
+employees.
+
+C<Person> is a B<superclass> of C<Employee>, and C<Employee> is a
+B<subclass> of C<Person>.
+
+ package Employee;
+
+ use parent 'Person';
+
+The L<parent> module is one of several ways that Perl lets you define
+inheritance relationships.
+
+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.
+
+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
+C<Employee::Permanent> and C<Employee::Temporary> classes to
+distinguish between different types of employees.
+
+=head3 Overriding methods and method resolution
+
+Inheritance allows two classes to share code. By default, every method
+in the parent class is also available in the child. The child can
+explicitly B<override> a parent's method to provide its own
+implementation. For example, if we have an C<Employee> object, it has
+the C<print_greeting()> method from person:
+
+ my $larry = Employee->new(
+ name => 'Larry Wall',
+ birth_date => '1954-09-27',
+ country_code => 'us',
+ job_title => 'Hacker Extraordinaire',
+ );
+
+ $larry->print_greeting; # Hello, Larry Wall
+
+If we wanted to include the employee's job title in the greeting, we
+could override the method:
+
+ package Employee;
+
+ use parent 'Person';
+
+ sub print_greeting {
+ my $self = shift;
+
+ print "Hello, ", $self->name, " - ", $self->job_title, "\n";
+ }
+
+ $larry->print_greeting; # Hello, Larry Wall - Hacker Extraordinaire
+
+The process of determining what method should be used is called
+B<method resolution>. What Perl does is look at the object's class
+first (C<Employee> in this case). If that class defines the method,
+then that class's version of the method is called. If not, Perl looks
+at each parent class in turn. For C<Employee>, its only parent is
+C<Person>. If C<Employee> does not define the method, but C<Person>
+does, then Perl calls the method in C<Person>.
+
+If C<Person> inherited from C<Animal>, which inherited from C<Thing>,
+then Perl would keep looking "up the chain" if necessary.
+
+It is possible to explicitly call a parent method from a child:
+
+ package Employee;
+
+ use parent 'Person';
+
+ sub print_greeting {
+ my $self = shift;
+
+ $self->SUPER::print_greeting();
+
+ print "Your job is ", $self->job_title, "\n";
+ }
+
+The C<SUPER::> bit tells Perl to look for the C<print_greeting()> in
+the C<Employee> class's inheritance chain. When it finds the parent
+class that implements this method, the method is called.
+
+We mentioned multiple inheritance earlier. The main problem with
+multiple inheritance is that it greatly complicates method resolution.
+See L<perlobj> for more details.
+
+=head2 Encapsulation
+
+B<Encapsulation> is the idea that an object is opaque. When another
+developer uses your class, they don't need to know I<how> it is
+implemented, they just need to know I<what> it does.
+
+Encapsulation is important for several reasons. First, it allows you to
+separate the public API from the private implementation. This means you
+can change that implementation without breaking the API.
+
+Second, when classes are well encapsulated, they become easier to
+subclass. Ideally, a subclass uses the same APIs to access object data
+that its parent class uses. In reality, subclassing sometimes involves
+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.
+
+=head2 Composition
+
+In object-oriented code, we often find that one object references
+another object. This is called B<composition>, or a B<has-a>
+relationship.
+
+Earlier, we mentioned that the C<Person> class's C<birth_date> accessor
+could return a L<DateTime> object. This is a perfect example of
+composition. We could go even further, and make objects for name and
+country as well. The C<Person> class would then be B<composed> of
+several other objects.
+
+=head2 Roles
+
+B<Roles> are something that a class I<does>, rather than something that
+it I<is>. Roles are relatively new to Perl, but have become rather
+popular. Roles are B<applied> to classes. Sometimes we say that classes
+B<consume> roles.
+
+Roles are an alternative to inheritance for providing polymorphism.
+Let's assume we have two classes, C<Radio> and C<Computer>. Both of
+these things have on/off switches. We want to model that in our class
+definitions.
+
+We could have both classes inherit from a common parent, like
+C<Machine>, but not all machines have on/off switches. We could create
+a parent class called C<HasOnOffSwitch>, but that is very artificial.
+Radios and computers are not specializations of this parent. This
+parent is really a rather ridiculous creation.
+
+This is where roles come in. It makes a lot of sense to create a
+C<HasOnOffSwitch> role and apply it to both classes. This role would
+define a known API like providing C<turn_on()> and C<turn_off()>
+methods.
+
+Perl does not have any built-in way to express roles. In the past,
+people just bit the bullet and used multiple inheritance. Nowadays,
+there are several good choices on CPAN for using roles.
+
+=head1 PERL OO SYSTEMS
+
+As we mentioned before, Perl's built-in OO system is very minimal, but
+also quite flexible. Over the years, many people have developed systems
+which build on top of Perl's built-in system to provide more features
+and convenience.
+
+We strongly recommend that you use one of these systems. Even the most
+minimal of them eliminates a lot of repetitive boilerplate. There's
+really no good reason to write your classes from scratch in Perl.
+
+If you are interested in the guts underlying these systems, check out
+L<perlobj>.
+
+=head2 Moose
+
+L<Moose> bills itself as a "postmodern object system for Perl 5". Don't
+be scared, the "postmodern" label is a callback to Larry's description
+of Perl as "the first postmodern computer language".
+
+C<Moose> provides a complete, modern OO system. Its biggest influence
+is the Common Lisp Object System, but it also borrows ideas from
+Smalltalk and several other languages. C<Moose> was created by Stevan
+Little, and draws heavily from his work on the Perl 6 OO design.
+
+C<Moose> provides a number of features:
+
+=over 4
+
+=item * Declarative sugar
+
+C<Moose> provides a layer of declarative "sugar" for defining classes.
+That sugar is just a set of exported functions that make declaring how
+your class works simpler and more palatable. This lets you describe
+I<what> your class is, rather than having to tell Perl I<how> to
+implement your class.
+
+Here's a simple but complete C<Moose> class:
+
+ package Person;
+ use Moose;
+
+ has name => ( is => 'ro' );
+ has birth_date => ( is => 'ro' );
+ has country_code => ( is => 'ro' );
+
+ sub print_greeting {
+ my $self = shift;
+
+ print "Hello, ", $self->name, "\n";
+ }
+
+The C<has()> subroutine declares an attribute, and C<Moose>
+automatically creates accessors for these attributes. It also takes
+care of creating a C<new()> method for you. This constructor knows
+about the attributes you declared, so you can set them when creating a
+new C<Person>.
+
+=item * Roles built-in
+
+C<Moose> lets you define roles the same way you define classes:
+
+ package HasOnOfSwitch;
+ use Moose::Role;
+
+ has is_on => (
+ is => 'rw',
+ isa => 'Bool',
+ );
+
+ sub turn_on {
+ my $self = shift;
+ $self->is_on(1);
+ }
+
+ sub turn_off {
+ my $self = shift;
+ $self->is_on(0);
+ }
+
+=item * A miniature type system
+
+In the example above, you can see that we passed C<< isa => 'Bool' >>
+to C<has()> when creating our C<is_on> attribute. This tells C<Moose>
+that this attribute must be a boolean value. If we try to set it to an
+invalid value, our code will throw an error.
+
+=item * Full introspection and manipulation
+
+Perl's built-in introspection features are fairly minimal. C<Moose>
+builds on top of them and creates a full introspection layer for your
+classes. This lets you ask questions like "what methods does the Person
+class implement?" It also lets you modify your classes
+programmatically.
+
+=item * Self-hosted and extensible
+
+C<Moose> describes itself using its own introspection API. Besides
+being a cool trick, this means that you can extend C<Moose> using
+C<Moose> itself.
+
+=item * Rich ecosystem
+
+There is a rich ecosystem of C<Moose> extensions on CPAN under the
+L<MooseX|http://search.cpan.org/search?query=MooseX&mode=dist>
+namespace. In addition, many modules on CPAN already use C<Moose>,
+providing you with lots of examples to learn from.
+
+=item * Many more features
+
+C<Moose> is a very powerful tool, and we can't cover all of its
+features here. We encourage you to learn more by reading the C<Moose>
+documentation, starting with
+L<Moose::Manual|http://search.cpan.org/perldoc?Moose::Manual>.
+
+=back
+
+Of course, C<Moose> isn't perfect.
+
+C<Moose> can make your code slower to load. C<Moose> itself is not
+small, and it does a I<lot> of code generation when you define your
+class. This code generation means that your runtime code is as fast as
+it can be, but you pay for this when your modules are first loaded.
+
+This load time hit can be a problem when startup speed is important,
+such as with a command-line script or a "plain vanilla" CGI script that
+must be loaded each time it is executed.
+
+Before you panic, know that many people do use C<Moose> for
+command-line tools and other startup-sensitive code. We encourage you
+to try C<Moose> out first before worrying about startup speed.
+
+C<Moose> also has several dependencies on other modules. Most of these
+are small stand-alone modules, a number of which have been spun off
+from C<Moose>. C<Moose> itself, and some of its dependencies, require a
+compiler. If you need to install your software on a system without a
+compiler, or if having I<any> dependencies is a problem, then C<Moose>
+may not be right for you.
+
+=head3 Mouse
+
+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
+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.
+
+The C<Moose> authors hope that one day C<Mouse> can be made obsolete by
+improving C<Moose> enough, but for now it provides a worthwhile
+alternative to C<Moose>.
+
+=head2 Class::Accessor
+
+L<Class::Accessor> is the polar opposite of C<Moose>. It provides very
+few features, nor is it self-hosting.
+
+It is, however, very simple, pure Perl, and it has no non-core
+dependencies. It also provides a "Moose-like" API on demand for the
+features it supports.
+
+Even though it doesn't do much, it is still preferable to writing your
+own classes from scratch.
+
+Here's our C<Person> class with C<Class::Accessor>:
+
+ package Person;
+ use Class::Accessor 'antlers';
+
+ has name => ( is => 'ro' );
+ has birth_date => ( is => 'ro' );
+ has country_code => ( is => 'ro' );
+
+ sub print_greeting {
+ my $self = shift;
+
+ print "Hello, ", $self->name, "\n";
+ }
+
+The C<antlers> import flag tells C<Class::Accessor> that you want to
+define your attributes using C<Moose>-like syntax. The only parameter
+that you can pass to C<has> is C<is>. We recommend that you use this
+Moose-like syntax if you choose C<Class::Accessor> since it means you
+will have a smoother upgrade path if you later decide to move to
+C<Moose>.
+
+Like C<Moose>, C<Class::Accessor> generates accessor methods and a
+constructor for your class.
+
+=head2 Object::Tiny
+
+Finally, we have L<Object::Tiny>. This module truly lives up to its
+name. It has an incredibly minimal API and absolutely no dependencies
+(core or not). Still, we think it's a lot easier to use than writing
+your own OO code from scratch.
+
+Here's our C<Person> class once more:
+
+ package Person;
+ use Object::Tiny qw( name birth_date country_code );
+
+ sub print_greeting {
+ my $self = shift;
+
+ print "Hello, ", $self->name, "\n";
+ }
+
+That's it!
+
+With C<Object::Tiny>, all accessors are read-only. It generates a
+constructor for you, as well as the accessors you define.
+
+=head2 Role::Tiny
+
+As we mentioned before, roles provide an alternative to inheritance,
+but Perl does not have any built-in role support. If you choose to use
+Moose, it comes with a full-fledged role implementation. However, if
+you use one of our other recommended OO modules, you can still use
+roles with L<Role::Tiny>
+
+C<Role::Tiny> provides some of the same features as Moose's role
+system, but in a much smaller package. Most notably, it doesn't support
+any sort of attribute declaration, so you have to do that by hand.
+Still, it's useful, and works well with C<Class::Accessor> and
+C<Object::Tiny>
+
+=head2 OO System Summary
+
+Here's a brief recap of the options we covered:
+
+=over 4
+
+=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
+doesn't work for your application.
+
+=item * L<Class::Accessor>
+
+C<Class::Accessor> does a lot less than C<Moose>, and is a nice
+alternative if you find C<Moose> overwhelming. It's been around a long
+time and is well battle-tested. It also has a minimal C<Moose>
+compatibility mode which makes moving from C<Class::Accessor> to
+C<Moose> easy.
+
+=item * L<Object::Tiny>
+
+C<Object::Tiny> is the absolute minimal option. It has no dependencies,
+and almost no syntax to learn. It's a good option for a super minimal
+environment and for throwing something together quickly without having
+to worry about details.
+
+=item * L<Role::Tiny>
+
+Use C<Role::Tiny> with C<Class::Accessor> or C<Object::Tiny> if you
+find yourself considering multiple inheritance. If you go with
+C<Moose>, it comes with its own role implementation.
+
+=back
+
+=head2 Other OO Systems
+
+There are literally dozens of other OO-related modules on CPAN besides
+those covered here, and you're likely to run across one or more of them
+if you work with other people's code.
+
+In addition, plenty of code in the wild does all of its OO "by hand",
+using just the Perl built-in OO features. If you need to maintain such
+code, you should read L<perlobj> to understand exactly how Perl's
+built-in OO works.
+
+=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.
+
+For small systems, L<Object::Tiny> and L<Class::Accessor> both provide
+minimal object systems that take care of basic boilerplate for you.
+
+For bigger projects, L<Moose> provides a rich set of features that will
+let you focus on implementing your business logic.
+
+We encourage you to play with and evaluate L<Moose>,
+L<Class::Accessor>, and L<Object::Tiny> to see which OO system is right
+for you.
+
+=cut