diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:43:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:43:11 +0000 |
commit | fc22b3d6507c6745911b9dfcc68f1e665ae13dbc (patch) | |
tree | ce1e3bce06471410239a6f41282e328770aa404a /upstream/mageia-cauldron/man1/perlootut.1 | |
parent | Initial commit. (diff) | |
download | manpages-l10n-fc22b3d6507c6745911b9dfcc68f1e665ae13dbc.tar.xz manpages-l10n-fc22b3d6507c6745911b9dfcc68f1e665ae13dbc.zip |
Adding upstream version 4.22.0.upstream/4.22.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'upstream/mageia-cauldron/man1/perlootut.1')
-rw-r--r-- | upstream/mageia-cauldron/man1/perlootut.1 | 785 |
1 files changed, 785 insertions, 0 deletions
diff --git a/upstream/mageia-cauldron/man1/perlootut.1 b/upstream/mageia-cauldron/man1/perlootut.1 new file mode 100644 index 00000000..4f8fb0e2 --- /dev/null +++ b/upstream/mageia-cauldron/man1/perlootut.1 @@ -0,0 +1,785 @@ +.\" -*- mode: troff; coding: utf-8 -*- +.\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. +.ie n \{\ +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "PERLOOTUT 1" +.TH PERLOOTUT 1 2023-11-28 "perl v5.38.2" "Perl Programmers Reference Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH NAME +perlootut \- Object\-Oriented Programming in Perl Tutorial +.SH DATE +.IX Header "DATE" +This document was created in February, 2011, and the last major +revision was in February, 2013. +.PP +If you are reading this in the future then it's possible that the state +of the art has changed. We recommend you start by reading the perlootut +document in the latest stable release of Perl, rather than this +version. +.SH DESCRIPTION +.IX Header "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 +CPAN <https://www.cpan.org> which build on top of what Perl +provides. +.PP +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. +.PP +If you want to know how Perl OO works under the hood, the perlobj +document explains the nitty gritty details. +.PP +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 perlintro first. You +should also read the perlsyn, perlop, and perlsub documents. +.SH "OBJECT-ORIENTED FUNDAMENTALS" +.IX Header "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. +.PP +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. +.SS Object +.IX Subsection "Object" +An \fBobject\fR is a data structure that bundles together data and +subroutines which operate on that data. An object's data is called +\&\fBattributes\fR, and its subroutines are called \fBmethods\fR. An object can +be thought of as a noun (a person, a web service, a computer). +.PP +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 \fI/etc/hostname\fR on a machine named "foo.example.com", +that object's path would be "/etc/hostname", its content would be +"foo\en", and it's last modification time would be 1304974868 seconds +since the beginning of the epoch. +.PP +The methods associated with a file might include \f(CWrename()\fR and +\&\f(CWwrite()\fR. +.PP +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. +.SS Class +.IX Subsection "Class" +A \fBclass\fR 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. +.PP +All objects belong to a specific class. For example, our +\&\fI/etc/hostname\fR object belongs to the \f(CW\*(C`File\*(C'\fR class. When we want to +create a specific object, we start with its class, and \fBconstruct\fR or +\&\fBinstantiate\fR an object. A specific object is often referred to as an +\&\fBinstance\fR of a class. +.PP +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 \f(CW\*(C`File\*(C'\fR class: +.PP +.Vb 1 +\& package File; +.Ve +.PP +In Perl, there is no special keyword for constructing an object. +However, most OO modules on CPAN use a method named \f(CWnew()\fR to +construct a new object: +.PP +.Vb 5 +\& my $hostname = File\->new( +\& path => \*(Aq/etc/hostname\*(Aq, +\& content => "foo\en", +\& last_mod_time => 1304974868, +\& ); +.Ve +.PP +(Don't worry about that \f(CW\*(C`\->\*(C'\fR operator, it will be explained +later.) +.PP +\fIBlessing\fR +.IX Subsection "Blessing" +.PP +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 \fBblessing\fR that data +structure using Perl's \f(CW\*(C`bless\*(C'\fR function. +.PP +While we strongly suggest you don't build your objects from scratch, +you should know the term \fBbless\fR. A \fBblessed\fR data structure (aka "a +referent") is an object. We sometimes say that an object has been +"blessed into a class". +.PP +Once a referent has been blessed, the \f(CW\*(C`blessed\*(C'\fR function from the +Scalar::Util core module can tell us its class name. This subroutine +returns an object's class when passed an object, and false otherwise. +.PP +.Vb 1 +\& use Scalar::Util \*(Aqblessed\*(Aq; +\& +\& print blessed($hash); # undef +\& print blessed($hostname); # File +.Ve +.PP +\fIConstructor\fR +.IX Subsection "Constructor" +.PP +A \fBconstructor\fR 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 \f(CW\*(C`new\*(C'\fR as the name for +their constructor: +.PP +.Vb 1 +\& my $file = File\->new(...); +.Ve +.SS Methods +.IX Subsection "Methods" +You already learned that a \fBmethod\fR is a subroutine that operates on +an object. You can think of a method as the things that an object can +\&\fIdo\fR. If an object is a noun, then methods are its verbs (save, print, +open). +.PP +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: +.PP +.Vb 2 +\& sub print_info { +\& my $self = shift; +\& +\& print "This file is at ", $self\->path, "\en"; +\& } +\& +\& $file\->print_info; +\& # The file is at /etc/hostname +.Ve +.PP +What makes a method special is \fIhow it's called\fR. The arrow operator +(\f(CW\*(C`\->\*(C'\fR) tells Perl that we are calling a method. +.PP +When we make a method call, Perl arranges for the method's \fBinvocant\fR +to be passed as the first argument. \fBInvocant\fR 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: +.PP +.Vb 3 +\& sub print_info { +\& my $self = shift; +\& my $prefix = shift // "This file is at "; +\& +\& print $prefix, ", ", $self\->path, "\en"; +\& } +\& +\& $file\->print_info("The file is located at "); +\& # The file is located at /etc/hostname +.Ve +.SS Attributes +.IX Subsection "Attributes" +Each class can define its \fBattributes\fR. When we instantiate an object, +we assign values to those attributes. For example, every \f(CW\*(C`File\*(C'\fR object +has a path. Attributes are sometimes called \fBproperties\fR. +.PP +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. +.PP +We recommend that you only access attributes via \fBaccessor\fR methods. +These are methods that can get or set the value of each attribute. We +saw this earlier in the \f(CWprint_info()\fR example, which calls \f(CW\*(C`$self\->path\*(C'\fR. +.PP +You might also see the terms \fBgetter\fR and \fBsetter\fR. These are two +types of accessors. A getter gets the attribute's value, while a setter +sets it. Another term for a setter is \fBmutator\fR +.PP +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. +.PP +The value of an attribute may itself be another object. For example, +instead of returning its last mod time as a number, the \f(CW\*(C`File\*(C'\fR class +could return a DateTime object representing that value. +.PP +It's possible to have a class that does not expose any publicly +settable attributes. Not every class has attributes and methods. +.SS Polymorphism +.IX Subsection "Polymorphism" +\&\fBPolymorphism\fR is a fancy way of saying that objects from two +different classes share an API. For example, we could have \f(CW\*(C`File\*(C'\fR and +\&\f(CW\*(C`WebPage\*(C'\fR classes which both have a \f(CWprint_content()\fR method. This +method might produce different output for each class, but they share a +common interface. +.PP +While the two classes may differ in many ways, when it comes to the +\&\f(CWprint_content()\fR method, they are the same. This means that we can +try to call the \f(CWprint_content()\fR method on an object of either class, +and \fBwe don't have to know what class the object belongs to!\fR +.PP +Polymorphism is one of the key concepts of object-oriented design. +.SS Inheritance +.IX Subsection "Inheritance" +\&\fBInheritance\fR lets you create a specialized version of an existing +class. Inheritance lets the new class reuse the methods and attributes +of another class. +.PP +For example, we could create an \f(CW\*(C`File::MP3\*(C'\fR class which \fBinherits\fR +from \f(CW\*(C`File\*(C'\fR. An \f(CW\*(C`File::MP3\*(C'\fR \fBis-a\fR \fImore specific\fR type of \f(CW\*(C`File\*(C'\fR. +All mp3 files are files, but not all files are mp3 files. +.PP +We often refer to inheritance relationships as \fBparent-child\fR or +\&\f(CW\*(C`superclass\*(C'\fR/\f(CW\*(C`subclass\*(C'\fR relationships. Sometimes we say that the +child has an \fBis-a\fR relationship with its parent class. +.PP +\&\f(CW\*(C`File\*(C'\fR is a \fBsuperclass\fR of \f(CW\*(C`File::MP3\*(C'\fR, and \f(CW\*(C`File::MP3\*(C'\fR is a +\&\fBsubclass\fR of \f(CW\*(C`File\*(C'\fR. +.PP +.Vb 1 +\& package File::MP3; +\& +\& use parent \*(AqFile\*(Aq; +.Ve +.PP +The parent module is one of several ways that Perl lets you define +inheritance relationships. +.PP +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 \fBroles\fR to do everything you can do +with multiple inheritance, but in a cleaner way. +.PP +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 +\&\f(CW\*(C`File::MP3::FixedBitrate\*(C'\fR and \f(CW\*(C`File::MP3::VariableBitrate\*(C'\fR classes to +distinguish between different types of mp3 file. +.PP +\fIOverriding methods and method resolution\fR +.IX Subsection "Overriding methods and method resolution" +.PP +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 \fBoverride\fR a parent's method to provide its own +implementation. For example, if we have an \f(CW\*(C`File::MP3\*(C'\fR object, it has +the \f(CWprint_info()\fR method from \f(CW\*(C`File\*(C'\fR: +.PP +.Vb 6 +\& my $cage = File::MP3\->new( +\& path => \*(Aqmp3s/My\-Body\-Is\-a\-Cage.mp3\*(Aq, +\& content => $mp3_data, +\& last_mod_time => 1304974868, +\& title => \*(AqMy Body Is a Cage\*(Aq, +\& ); +\& +\& $cage\->print_info; +\& # The file is at mp3s/My\-Body\-Is\-a\-Cage.mp3 +.Ve +.PP +If we wanted to include the mp3's title in the greeting, we could +override the method: +.PP +.Vb 1 +\& package File::MP3; +\& +\& use parent \*(AqFile\*(Aq; +\& +\& sub print_info { +\& my $self = shift; +\& +\& print "This file is at ", $self\->path, "\en"; +\& print "Its title is ", $self\->title, "\en"; +\& } +\& +\& $cage\->print_info; +\& # The file is at mp3s/My\-Body\-Is\-a\-Cage.mp3 +\& # Its title is My Body Is a Cage +.Ve +.PP +The process of determining what method should be used is called +\&\fBmethod resolution\fR. What Perl does is look at the object's class +first (\f(CW\*(C`File::MP3\*(C'\fR 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 \f(CW\*(C`File::MP3\*(C'\fR, its only parent is +\&\f(CW\*(C`File\*(C'\fR. If \f(CW\*(C`File::MP3\*(C'\fR does not define the method, but \f(CW\*(C`File\*(C'\fR does, +then Perl calls the method in \f(CW\*(C`File\*(C'\fR. +.PP +If \f(CW\*(C`File\*(C'\fR inherited from \f(CW\*(C`DataSource\*(C'\fR, which inherited from \f(CW\*(C`Thing\*(C'\fR, +then Perl would keep looking "up the chain" if necessary. +.PP +It is possible to explicitly call a parent method from a child: +.PP +.Vb 1 +\& package File::MP3; +\& +\& use parent \*(AqFile\*(Aq; +\& +\& sub print_info { +\& my $self = shift; +\& +\& $self\->SUPER::print_info(); +\& print "Its title is ", $self\->title, "\en"; +\& } +.Ve +.PP +The \f(CW\*(C`SUPER::\*(C'\fR bit tells Perl to look for the \f(CWprint_info()\fR in the +\&\f(CW\*(C`File::MP3\*(C'\fR class's inheritance chain. When it finds the parent class +that implements this method, the method is called. +.PP +We mentioned multiple inheritance earlier. The main problem with +multiple inheritance is that it greatly complicates method resolution. +See perlobj for more details. +.SS Encapsulation +.IX Subsection "Encapsulation" +\&\fBEncapsulation\fR is the idea that an object is opaque. When another +developer uses your class, they don't need to know \fIhow\fR it is +implemented, they just need to know \fIwhat\fR it does. +.PP +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. +.PP +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. +.PP +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. +.SS Composition +.IX Subsection "Composition" +In object-oriented code, we often find that one object references +another object. This is called \fBcomposition\fR, or a \fBhas-a\fR +relationship. +.PP +Earlier, we mentioned that the \f(CW\*(C`File\*(C'\fR class's \f(CW\*(C`last_mod_time\*(C'\fR +accessor could return a DateTime object. This is a perfect example +of composition. We could go even further, and make the \f(CW\*(C`path\*(C'\fR and +\&\f(CW\*(C`content\*(C'\fR accessors return objects as well. The \f(CW\*(C`File\*(C'\fR class would +then be \fBcomposed\fR of several other objects. +.SS Roles +.IX Subsection "Roles" +\&\fBRoles\fR are something that a class \fIdoes\fR, rather than something that +it \fIis\fR. Roles are relatively new to Perl, but have become rather +popular. Roles are \fBapplied\fR to classes. Sometimes we say that classes +\&\fBconsume\fR roles. +.PP +Roles are an alternative to inheritance for providing polymorphism. +Let's assume we have two classes, \f(CW\*(C`Radio\*(C'\fR and \f(CW\*(C`Computer\*(C'\fR. Both of +these things have on/off switches. We want to model that in our class +definitions. +.PP +We could have both classes inherit from a common parent, like +\&\f(CW\*(C`Machine\*(C'\fR, but not all machines have on/off switches. We could create +a parent class called \f(CW\*(C`HasOnOffSwitch\*(C'\fR, but that is very artificial. +Radios and computers are not specializations of this parent. This +parent is really a rather ridiculous creation. +.PP +This is where roles come in. It makes a lot of sense to create a +\&\f(CW\*(C`HasOnOffSwitch\*(C'\fR role and apply it to both classes. This role would +define a known API like providing \f(CWturn_on()\fR and \f(CWturn_off()\fR +methods. +.PP +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. +.SS "When to Use OO" +.IX Subsection "When to Use OO" +Object Orientation is not the best solution to every problem. In \fIPerl +Best Practices\fR (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: +.IP \(bu 4 +The system being designed is large, or is likely to become large. +.IP \(bu 4 +The data can be aggregated into obvious structures, especially if +there's a large amount of data in each aggregate. +.IP \(bu 4 +The various types of data aggregate form a natural hierarchy that +facilitates the use of inheritance and polymorphism. +.IP \(bu 4 +You have a piece of data on which many different operations are +applied. +.IP \(bu 4 +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. +.IP \(bu 4 +It's likely you'll have to add new data types later. +.IP \(bu 4 +The typical interactions between pieces of data are best represented by +operators. +.IP \(bu 4 +The implementation of individual components of the system is likely to +change over time. +.IP \(bu 4 +The system design is already object-oriented. +.IP \(bu 4 +Large numbers of other programmers will be using your code modules. +.SH "PERL OO SYSTEMS" +.IX Header "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. +.PP +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. +.PP +If you are interested in the guts underlying these systems, check out +perlobj. +.SS Moose +.IX Subsection "Moose" +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". +.PP +\&\f(CW\*(C`Moose\*(C'\fR 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. \f(CW\*(C`Moose\*(C'\fR was created by Stevan +Little, and draws heavily from his work on the Raku OO design. +.PP +Here is our \f(CW\*(C`File\*(C'\fR class using \f(CW\*(C`Moose\*(C'\fR: +.PP +.Vb 2 +\& package File; +\& use Moose; +\& +\& has path => ( is => \*(Aqro\*(Aq ); +\& has content => ( is => \*(Aqro\*(Aq ); +\& has last_mod_time => ( is => \*(Aqro\*(Aq ); +\& +\& sub print_info { +\& my $self = shift; +\& +\& print "This file is at ", $self\->path, "\en"; +\& } +.Ve +.PP +\&\f(CW\*(C`Moose\*(C'\fR provides a number of features: +.IP \(bu 4 +Declarative sugar +.Sp +\&\f(CW\*(C`Moose\*(C'\fR 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 +\&\fIwhat\fR your class is, rather than having to tell Perl \fIhow\fR to +implement your class. +.Sp +The \f(CWhas()\fR subroutine declares an attribute, and \f(CW\*(C`Moose\*(C'\fR +automatically creates accessors for these attributes. It also takes +care of creating a \f(CWnew()\fR method for you. This constructor knows +about the attributes you declared, so you can set them when creating a +new \f(CW\*(C`File\*(C'\fR. +.IP \(bu 4 +Roles built-in +.Sp +\&\f(CW\*(C`Moose\*(C'\fR lets you define roles the same way you define classes: +.Sp +.Vb 2 +\& package HasOnOffSwitch; +\& use Moose::Role; +\& +\& has is_on => ( +\& is => \*(Aqrw\*(Aq, +\& isa => \*(AqBool\*(Aq, +\& ); +\& +\& sub turn_on { +\& my $self = shift; +\& $self\->is_on(1); +\& } +\& +\& sub turn_off { +\& my $self = shift; +\& $self\->is_on(0); +\& } +.Ve +.IP \(bu 4 +A miniature type system +.Sp +In the example above, you can see that we passed \f(CW\*(C`isa => \*(AqBool\*(Aq\*(C'\fR +to \f(CWhas()\fR when creating our \f(CW\*(C`is_on\*(C'\fR attribute. This tells \f(CW\*(C`Moose\*(C'\fR +that this attribute must be a boolean value. If we try to set it to an +invalid value, our code will throw an error. +.IP \(bu 4 +Full introspection and manipulation +.Sp +Perl's built-in introspection features are fairly minimal. \f(CW\*(C`Moose\*(C'\fR +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. +.IP \(bu 4 +Self-hosted and extensible +.Sp +\&\f(CW\*(C`Moose\*(C'\fR describes itself using its own introspection API. Besides +being a cool trick, this means that you can extend \f(CW\*(C`Moose\*(C'\fR using +\&\f(CW\*(C`Moose\*(C'\fR itself. +.IP \(bu 4 +Rich ecosystem +.Sp +There is a rich ecosystem of \f(CW\*(C`Moose\*(C'\fR extensions on CPAN under the +MooseX <https://metacpan.org/search?q=MooseX> +namespace. In addition, many modules on CPAN already use \f(CW\*(C`Moose\*(C'\fR, +providing you with lots of examples to learn from. +.IP \(bu 4 +Many more features +.Sp +\&\f(CW\*(C`Moose\*(C'\fR is a very powerful tool, and we can't cover all of its +features here. We encourage you to learn more by reading the \f(CW\*(C`Moose\*(C'\fR +documentation, starting with +Moose::Manual <https://metacpan.org/pod/Moose::Manual>. +.PP +Of course, \f(CW\*(C`Moose\*(C'\fR isn't perfect. +.PP +\&\f(CW\*(C`Moose\*(C'\fR can make your code slower to load. \f(CW\*(C`Moose\*(C'\fR itself is not +small, and it does a \fIlot\fR 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. +.PP +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. +.PP +Before you panic, know that many people do use \f(CW\*(C`Moose\*(C'\fR for +command-line tools and other startup-sensitive code. We encourage you +to try \f(CW\*(C`Moose\*(C'\fR out first before worrying about startup speed. +.PP +\&\f(CW\*(C`Moose\*(C'\fR also has several dependencies on other modules. Most of these +are small stand-alone modules, a number of which have been spun off +from \f(CW\*(C`Moose\*(C'\fR. \f(CW\*(C`Moose\*(C'\fR 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 \fIany\fR dependencies is a problem, then \f(CW\*(C`Moose\*(C'\fR +may not be right for you. +.PP +\fIMoo\fR +.IX Subsection "Moo" +.PP +If you try \f(CW\*(C`Moose\*(C'\fR and find that one of these issues is preventing you +from using \f(CW\*(C`Moose\*(C'\fR, we encourage you to consider Moo next. \f(CW\*(C`Moo\*(C'\fR +implements a subset of \f(CW\*(C`Moose\*(C'\fR's functionality in a simpler package. +For most features that it does implement, the end-user API is +\&\fIidentical\fR to \f(CW\*(C`Moose\*(C'\fR, meaning you can switch from \f(CW\*(C`Moo\*(C'\fR to +\&\f(CW\*(C`Moose\*(C'\fR quite easily. +.PP +\&\f(CW\*(C`Moo\*(C'\fR does not implement most of \f(CW\*(C`Moose\*(C'\fR'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. +.PP +One of \f(CW\*(C`Moo\*(C'\fR's most compelling features is its interoperability with +\&\f(CW\*(C`Moose\*(C'\fR. When someone tries to use \f(CW\*(C`Moose\*(C'\fR's introspection API on a +\&\f(CW\*(C`Moo\*(C'\fR class or role, it is transparently inflated into a \f(CW\*(C`Moose\*(C'\fR +class or role. This makes it easier to incorporate \f(CW\*(C`Moo\*(C'\fR\-using code +into a \f(CW\*(C`Moose\*(C'\fR code base and vice versa. +.PP +For example, a \f(CW\*(C`Moose\*(C'\fR class can subclass a \f(CW\*(C`Moo\*(C'\fR class using +\&\f(CW\*(C`extends\*(C'\fR or consume a \f(CW\*(C`Moo\*(C'\fR role using \f(CW\*(C`with\*(C'\fR. +.PP +The \f(CW\*(C`Moose\*(C'\fR authors hope that one day \f(CW\*(C`Moo\*(C'\fR can be made obsolete by +improving \f(CW\*(C`Moose\*(C'\fR enough, but for now it provides a worthwhile +alternative to \f(CW\*(C`Moose\*(C'\fR. +.SS Class::Accessor +.IX Subsection "Class::Accessor" +Class::Accessor is the polar opposite of \f(CW\*(C`Moose\*(C'\fR. It provides very +few features, nor is it self-hosting. +.PP +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. +.PP +Even though it doesn't do much, it is still preferable to writing your +own classes from scratch. +.PP +Here's our \f(CW\*(C`File\*(C'\fR class with \f(CW\*(C`Class::Accessor\*(C'\fR: +.PP +.Vb 2 +\& package File; +\& use Class::Accessor \*(Aqantlers\*(Aq; +\& +\& has path => ( is => \*(Aqro\*(Aq ); +\& has content => ( is => \*(Aqro\*(Aq ); +\& has last_mod_time => ( is => \*(Aqro\*(Aq ); +\& +\& sub print_info { +\& my $self = shift; +\& +\& print "This file is at ", $self\->path, "\en"; +\& } +.Ve +.PP +The \f(CW\*(C`antlers\*(C'\fR import flag tells \f(CW\*(C`Class::Accessor\*(C'\fR that you want to +define your attributes using \f(CW\*(C`Moose\*(C'\fR\-like syntax. The only parameter +that you can pass to \f(CW\*(C`has\*(C'\fR is \f(CW\*(C`is\*(C'\fR. We recommend that you use this +Moose-like syntax if you choose \f(CW\*(C`Class::Accessor\*(C'\fR since it means you +will have a smoother upgrade path if you later decide to move to +\&\f(CW\*(C`Moose\*(C'\fR. +.PP +Like \f(CW\*(C`Moose\*(C'\fR, \f(CW\*(C`Class::Accessor\*(C'\fR generates accessor methods and a +constructor for your class. +.SS Class::Tiny +.IX Subsection "Class::Tiny" +Finally, we have Class::Tiny. This module truly lives up to its +name. It has an incredibly minimal API and absolutely no dependencies +on any recent Perl. Still, we think it's a lot easier to use than +writing your own OO code from scratch. +.PP +Here's our \f(CW\*(C`File\*(C'\fR class once more: +.PP +.Vb 2 +\& package File; +\& use Class::Tiny qw( path content last_mod_time ); +\& +\& sub print_info { +\& my $self = shift; +\& +\& print "This file is at ", $self\->path, "\en"; +\& } +.Ve +.PP +That's it! +.PP +With \f(CW\*(C`Class::Tiny\*(C'\fR, all accessors are read-write. It generates a +constructor for you, as well as the accessors you define. +.PP +You can also use Class::Tiny::Antlers for \f(CW\*(C`Moose\*(C'\fR\-like syntax. +.SS Role::Tiny +.IX Subsection "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 Role::Tiny +.PP +\&\f(CW\*(C`Role::Tiny\*(C'\fR 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 \f(CW\*(C`Class::Accessor\*(C'\fR and +\&\f(CW\*(C`Class::Tiny\*(C'\fR +.SS "OO System Summary" +.IX Subsection "OO System Summary" +Here's a brief recap of the options we covered: +.IP \(bu 4 +Moose +.Sp +\&\f(CW\*(C`Moose\*(C'\fR is the maximal option. It has a lot of features, a big +ecosystem, and a thriving user base. We also covered Moo briefly. +\&\f(CW\*(C`Moo\*(C'\fR is \f(CW\*(C`Moose\*(C'\fR lite, and a reasonable alternative when Moose +doesn't work for your application. +.IP \(bu 4 +Class::Accessor +.Sp +\&\f(CW\*(C`Class::Accessor\*(C'\fR does a lot less than \f(CW\*(C`Moose\*(C'\fR, and is a nice +alternative if you find \f(CW\*(C`Moose\*(C'\fR overwhelming. It's been around a long +time and is well battle-tested. It also has a minimal \f(CW\*(C`Moose\*(C'\fR +compatibility mode which makes moving from \f(CW\*(C`Class::Accessor\*(C'\fR to +\&\f(CW\*(C`Moose\*(C'\fR easy. +.IP \(bu 4 +Class::Tiny +.Sp +\&\f(CW\*(C`Class::Tiny\*(C'\fR 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. +.IP \(bu 4 +Role::Tiny +.Sp +Use \f(CW\*(C`Role::Tiny\*(C'\fR with \f(CW\*(C`Class::Accessor\*(C'\fR or \f(CW\*(C`Class::Tiny\*(C'\fR if you find +yourself considering multiple inheritance. If you go with \f(CW\*(C`Moose\*(C'\fR, it +comes with its own role implementation. +.SS "Other OO Systems" +.IX Subsection "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. +.PP +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 perlobj to understand exactly how Perl's +built-in OO works. +.SH CONCLUSION +.IX Header "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. +.PP +For small systems, Class::Tiny and Class::Accessor both provide +minimal object systems that take care of basic boilerplate for you. +.PP +For bigger projects, Moose provides a rich set of features that will +let you focus on implementing your business logic. Moo provides a +nice alternative to Moose when you want a lot of features but need +faster compile time or to avoid XS. +.PP +We encourage you to play with and evaluate Moose, Moo, +Class::Accessor, and Class::Tiny to see which OO system is right +for you. |