diff options
Diffstat (limited to 'Master/tlpkg/tlperl/lib/pods/perlootut.pod')
-rw-r--r-- | Master/tlpkg/tlperl/lib/pods/perlootut.pod | 741 |
1 files changed, 0 insertions, 741 deletions
diff --git a/Master/tlpkg/tlperl/lib/pods/perlootut.pod b/Master/tlpkg/tlperl/lib/pods/perlootut.pod deleted file mode 100644 index b2e3500b358..00000000000 --- a/Master/tlpkg/tlperl/lib/pods/perlootut.pod +++ /dev/null @@ -1,741 +0,0 @@ -=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 file. The attributes for a file object might include -its path, content, and last modification time. If we created an object -to represent F</etc/hostname> on a machine named "foo.example.com", -that object's path would be "/etc/hostname", its content would be -"foo\n", and it's last modification time would be 1304974868 seconds -since the beginning of the epoch. - -The methods associated with a file might include C<rename()> and -C<write()>. - -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 - -A B<class> defines the behavior of a category of objects. A class is a -name for a category (like "File"), and a class also defines the -behavior of objects in that category. - -All objects belong to a specific class. For example, our -F</etc/hostname> object belongs to the C<File> 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 C<File> class: - - package File; - -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 $hostname = File->new( - path => '/etc/hostname', - content => "foo\n", - last_mod_time => 1304974868, - ); - -(Don't worry about that C<< -> >> operator, it will be explained -later.) - -=head3 Blessing - -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> data structure (aka "a -referent") is an object. We sometimes say that an object has been -"blessed into a class". - -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. - - use Scalar::Util 'blessed'; - - print blessed($hash); # undef - print blessed($hostname); # File - -=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. 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 -argument: - - sub print_info { - my $self = shift; - - print "This file is at ", $self->path, "\n"; - } - - $file->print_info; - # The file is at /etc/hostname - -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_info { - my $self = shift; - my $prefix = shift // "This file is at "; - - print $prefix, ", ", $self->path, "\n"; - } - - $file->print_info("The file is located at "); - # The file is located at /etc/hostname - -=head2 Attributes - -Each class can define its B<attributes>. When we instantiate an object, -we assign values to those attributes. For example, every C<File> object -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 underlying hash, 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_info()> example, which calls C<< -$self->path >>. - -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. 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 -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 last mod time as a number, the C<File> class -could return a L<DateTime> object representing that value. - -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<File> and -C<WebPage> classes which both have a C<print_content()> method. This -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 -try to call the C<print_content()> 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> lets you create a specialized version of an existing -class. Inheritance lets the new class to reuse the methods and -attributes of another 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>. - - package File::MP3; - - use parent 'File'; - -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, 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 -C<File::MP3::FixedBitrate> and C<File::MP3::VariableBitrate> classes to -distinguish between different types of mp3 file. - -=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<File::MP3> object, it has -the C<print_info()> method from C<File>: - - my $cage = File::MP3->new( - path => 'mp3s/My-Body-Is-a-Cage.mp3', - content => $mp3_data, - last_mod_time => 1304974868, - title => 'My Body Is a Cage', - ); - - $cage->print_info; - # The file is at mp3s/My-Body-Is-a-Cage.mp3 - -If we wanted to include the mp3's title in the greeting, we could -override the method: - - package File::MP3; - - use parent 'File'; - - sub print_info { - my $self = shift; - - print "This file is at ", $self->path, "\n"; - print "Its title is ", $self->title, "\n"; - } - - $cage->print_info; - # The file is at mp3s/My-Body-Is-a-Cage.mp3 - # Its title is My Body Is a Cage - -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<File::MP3> 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<File::MP3>, its only parent is -C<File>. If C<File::MP3> does not define the method, but C<File> does, -then Perl calls the method in C<File>. - -If C<File> inherited from C<DataSource>, 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 File::MP3; - - use parent 'File'; - - sub print_info { - my $self = shift; - - $self->SUPER::print_info(); - print "Its title is ", $self->title, "\n"; - } - -The C<SUPER::> bit tells Perl to look for the C<print_info()> in the -C<File::MP3> 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 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 - -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<File> class's C<last_mod_time> -accessor could return a L<DateTime> object. This is a perfect example -of composition. We could go even further, and make the C<path> and -C<content> accessors return objects as well. The C<File> 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. - -=head2 When to Use OO - -Object Orientation is not the best solution to every problem. In I<Perl -Best Practices> (copyright 2004, Published by O'Reilly Media, Inc.), -Damian Conway provides a list of criteria to use when deciding if OO is -the right fit for your problem: - -=over 4 - -=item * - -The system being designed is large, or is likely to become large. - -=item * - -The data can be aggregated into obvious structures, especially if -there's a large amount of data in each aggregate. - -=item * - -The various types of data aggregate form a natural hierarchy that -facilitates the use of inheritance and polymorphism. - -=item * - -You have a piece of data on which many different operations are -applied. - -=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 * - -It's likely you'll have to add new data types later. - -=item * - -The typical interactions between pieces of data are best represented by -operators. - -=item * - -The implementation of individual components of the system is likely to -change over time. - -=item * - -The system design is already object-oriented. - -=item * - -Large numbers of other programmers will be using your code modules. - -=back - -=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. - -Here is our C<File> class using C<Moose>: - - package File; - use Moose; - - has path => ( is => 'ro' ); - has content => ( is => 'ro' ); - has last_mod_time => ( is => 'ro' ); - - sub print_info { - my $self = shift; - - print "This file is at ", $self->path, "\n"; - } - -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. - -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<File>. - -=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 File -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, all of its -I<required> dependencies ship with the Perl core, and it 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<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<File> class with C<Class::Accessor>: - - package File; - use Class::Accessor 'antlers'; - - has path => ( is => 'ro' ); - has content => ( is => 'ro' ); - has last_mod_time => ( is => 'ro' ); - - sub print_info { - my $self = shift; - - print "This file is at ", $self->path, "\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<File> class once more: - - package File; - use Object::Tiny qw( path content last_mod_time ); - - sub print_info { - my $self = shift; - - print "This file is at ", $self->path, "\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 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. - -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 |