perltoot.pod
来自「MSYS在windows下模拟了一个类unix的终端」· POD 代码 · 共 1,734 行 · 第 1/5 页
POD
1,734 行
=head1 NAMEperltoot - Tom's object-oriented tutorial for perl=head1 DESCRIPTIONObject-oriented programming is a big seller these days. Some managerswould rather have objects than sliced bread. Why is that? What's sospecial about an object? Just what I<is> an object anyway?An object is nothing but a way of tucking away complex behaviours intoa neat little easy-to-use bundle. (This is what professors callabstraction.) Smart people who have nothing to do but sit around forweeks on end figuring out really hard problems make these niftyobjects that even regular people can use. (This is what professors callsoftware reuse.) Users (well, programmers) can play with this littlebundle all they want, but they aren't to open it up and mess with theinsides. Just like an expensive piece of hardware, the contract saysthat you void the warranty if you muck with the cover. So don't do that.The heart of objects is the class, a protected little private namespacefull of data and functions. A class is a set of related routines thataddresses some problem area. You can think of it as a user-defined type.The Perl package mechanism, also used for more traditional modules,is used for class modules as well. Objects "live" in a class, meaningthat they belong to some package.More often than not, the class provides the user with little bundles.These bundles are objects. They know whose class they belong to,and how to behave. Users ask the class to do something, like "giveme an object." Or they can ask one of these objects to do something.Asking a class to do something for you is calling a I<class method>.Asking an object to do something for you is calling an I<object method>.Asking either a class (usually) or an object (sometimes) to give youback an object is calling a I<constructor>, which is just akind of method.That's all well and good, but how is an object different from any otherPerl data type? Just what is an object I<really>; that is, what's itsfundamental type? The answer to the first question is easy. An objectis different from any other data type in Perl in one and only one way:you may dereference it using not merely string or numeric subscriptsas with simple arrays and hashes, but with named subroutine calls.In a word, with I<methods>.The answer to the second question is that it's a reference, and not justany reference, mind you, but one whose referent has been I<bless>()edinto a particular class (read: package). What kind of reference? Well,the answer to that one is a bit less concrete. That's because in Perlthe designer of the class can employ any sort of reference they'd likeas the underlying intrinsic data type. It could be a scalar, an array,or a hash reference. It could even be a code reference. But becauseof its inherent flexibility, an object is usually a hash reference.=head1 Creating a ClassBefore you create a class, you need to decide what to name it. That'sbecause the class (package) name governs the name of the file used tohouse it, just as with regular modules. Then, that class (package)should provide one or more ways to generate objects. Finally, it shouldprovide mechanisms to allow users of its objects to indirectly manipulatethese objects from a distance.For example, let's make a simple Person class module. It gets stored inthe file Person.pm. If it were called a Happy::Person class, it wouldbe stored in the file Happy/Person.pm, and its package would becomeHappy::Person instead of just Person. (On a personal computer notrunning Unix or Plan 9, but something like MacOS or VMS, the directoryseparator may be different, but the principle is the same.) Do not assumeany formal relationship between modules based on their directory names.This is merely a grouping convenience, and has no effect on inheritance,variable accessibility, or anything else.For this module we aren't going to use Exporter, because we'rea well-behaved class module that doesn't export anything at all.In order to manufacture objects, a class needs to have a I<constructormethod>. A constructor gives you back not just a regular data type,but a brand-new object in that class. This magic is taken care of bythe bless() function, whose sole purpose is to enable its referent tobe used as an object. Remember: being an object really means nothingmore than that methods may now be called against it.While a constructor may be named anything you'd like, most Perlprogrammers seem to like to call theirs new(). However, new() is nota reserved word, and a class is under no obligation to supply such.Some programmers have also been known to use a function withthe same name as the class as the constructor.=head2 Object RepresentationBy far the most common mechanism used in Perl to represent a Pascalrecord, a C struct, or a C++ class is an anonymous hash. That's because ahash has an arbitrary number of data fields, each conveniently accessed byan arbitrary name of your own devising.If you were just doing a simplestruct-like emulation, you would likely go about it something like this: $rec = { name => "Jason", age => 23, peers => [ "Norbert", "Rhys", "Phineas"], };If you felt like it, you could add a bit of visual distinctionby up-casing the hash keys: $rec = { NAME => "Jason", AGE => 23, PEERS => [ "Norbert", "Rhys", "Phineas"], };And so you could get at C<< $rec->{NAME} >> to find "Jason", orC<< @{ $rec->{PEERS} } >> to get at "Norbert", "Rhys", and "Phineas".(Have you ever noticed how many 23-year-old programmers seem tobe named "Jason" these days? :-)This same model is often used for classes, although it is not consideredthe pinnacle of programming propriety for folks from outside theclass to come waltzing into an object, brazenly accessing its datamembers directly. Generally speaking, an object should be consideredan opaque cookie that you use I<object methods> to access. Visually,methods look like you're dereffing a reference using a function nameinstead of brackets or braces.=head2 Class InterfaceSome languages provide a formal syntactic interface to a class's methods,but Perl does not. It relies on you to read the documentation of eachclass. If you try to call an undefined method on an object, Perl won'tcomplain, but the program will trigger an exception while it's running.Likewise, if you call a method expecting a prime number as its argumentwith a non-prime one instead, you can't expect the compiler to catch this.(Well, you can expect it all you like, but it's not going to happen.)Let's suppose you have a well-educated user of your Person class,someone who has read the docs that explain the prescribedinterface. Here's how they might use the Person class: use Person; $him = Person->new(); $him->name("Jason"); $him->age(23); $him->peers( "Norbert", "Rhys", "Phineas" ); push @All_Recs, $him; # save object in array for later printf "%s is %d years old.\n", $him->name, $him->age; print "His peers are: ", join(", ", $him->peers), "\n"; printf "Last rec's name is %s\n", $All_Recs[-1]->name;As you can see, the user of the class doesn't know (or at least, has nobusiness paying attention to the fact) that the object has one particularimplementation or another. The interface to the class and its objectsis exclusively via methods, and that's all the user of the class shouldever play with.=head2 Constructors and Instance MethodsStill, I<someone> has to know what's in the object. And that someone isthe class. It implements methods that the programmer uses to accessthe object. Here's how to implement the Person class using the standardhash-ref-as-an-object idiom. We'll make a class method called new() toact as the constructor, and three object methods called name(), age(), andpeers() to get at per-object data hidden away in our anonymous hash. package Person; use strict; ################################################## ## the object constructor (simplistic version) ## ################################################## sub new { my $self = {}; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless($self); # but see below return $self; } ############################################## ## methods to access per-object data ## ## ## ## With args, they set the value. Without ## ## any, they only retrieve it/them. ## ############################################## sub name { my $self = shift; if (@_) { $self->{NAME} = shift } return $self->{NAME}; } sub age { my $self = shift; if (@_) { $self->{AGE} = shift } return $self->{AGE}; } sub peers { my $self = shift; if (@_) { @{ $self->{PEERS} } = @_ } return @{ $self->{PEERS} }; } 1; # so the require or use succeedsWe've created three methods to access an object's data, name(), age(),and peers(). These are all substantially similar. If called with anargument, they set the appropriate field; otherwise they return thevalue held by that field, meaning the value of that hash key.=head2 Planning for the Future: Better ConstructorsEven though at this point you may not even know what it means, somedayyou're going to worry about inheritance. (You can safely ignore thisfor now and worry about it later if you'd like.) To ensure that thisall works out smoothly, you must use the double-argument form of bless().The second argument is the class into which the referent will be blessed.By not assuming our own class as the default second argument and insteadusing the class passed into us, we make our constructor inheritable.While we're at it, let's make our constructor a bit more flexible.Rather than being uniquely a class method, we'll set it up so thatit can be called as either a class method I<or> an objectmethod. That way you can say: $me = Person->new(); $him = $me->new();To do this, all we have to do is check whether what was passed inwas a reference or not. If so, we were invoked as an object method,and we need to extract the package (class) using the ref() function.If not, we just use the string passed in as the package namefor blessing our referent. sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless ($self, $class); return $self; }That's about all there is for constructors. These methods bring objectsto life, returning neat little opaque bundles to the user to be used insubsequent method calls.=head2 DestructorsEvery story has a beginning and an end. The beginning of the object'sstory is its constructor, explicitly called when the object comes intoexistence. But the ending of its story is the I<destructor>, a methodimplicitly called when an object leaves this life. Any per-objectclean-up code is placed in the destructor, which must (in Perl) be calledDESTROY.If constructors can have arbitrary names, then why not destructors?Because while a constructor is explicitly called, a destructor is not.Destruction happens automatically via Perl's garbage collection (GC)system, which is a quick but somewhat lazy reference-based GC system.To know what to call, Perl insists that the destructor be named DESTROY.Perl's notion of the right time to call a destructor is not well-definedcurrently, which is why your destructors should not rely on when they arecalled.Why is DESTROY in all caps? Perl on occasion uses purely uppercasefunction names as a convention to indicate that the function willbe automatically called by Perl in some way. Others that are calledimplicitly include BEGIN, END, AUTOLOAD, plus all methods used bytied objects, described in L<perltie>.In really good object-oriented programming languages, the user doesn'tcare when the destructor is called. It just happens when it's supposedto. In low-level languages without any GC at all, there's no way todepend on this happening at the right time, so the programmer mustexplicitly call the destructor to clean up memory and state, crossingtheir fingers that it's the right time to do so. Unlike C++, anobject destructor is nearly never needed in Perl, and even when it is,explicit invocation is uncalled for. In the case of our Person class,we don't need a destructor because Perl takes care of simple matterslike memory deallocation.The only situation where Perl's reference-based GC won't work iswhen there's a circularity in the data structure, such as: $this->{WHATEVER} = $this;In that case, you must delete the self-reference manually if you expectyour program not to leak memory. While admittedly error-prone, this isthe best we can do right now. Nonetheless, rest assured that when yourprogram is finished, its objects' destructors are all duly called.So you are guaranteed that an object I<eventually> gets properlydestroyed, except in the unique case of a program that never exits.(If you're running Perl embedded in another application, this full GCpass happens a bit more frequently--whenever a thread shuts down.)=head2 Other Object MethodsThe methods we've talked about so far have either been constructors orelse simple "data methods", interfaces to data stored in the object.These are a bit like an object's data members in the C++ world, exceptthat strangers don't access them as data. Instead, they should onlyaccess the object's data indirectly via its methods. This is animportant rule: in Perl, access to an object's data should I<only>be made through methods.Perl doesn't impose restrictions on who gets to use which methods.The public-versus-private distinction is by convention, not syntax.(Well, unless you use the Alias module described below inL<Data Members as Variables>.) Occasionally you'll see method names beginning or endingwith an underscore or two. This marking is a convention indicatingthat the methods are private to that class alone and sometimes to itsclosest acquaintances, its immediate subclasses. But this distinctionis not enforced by Perl itself. It's up to the programmer to behave.There's no reason to limit methods to those that simply access data.Methods can do anything at all. The key point is that they're invokedagainst an object or a class. Let's say we'd like object methods thatdo more than fetch or set one particular field. sub exclaim { my $self = shift; return sprintf "Hi, I'm %s, age %d, working with %s", $self->{NAME}, $self->{AGE}, join(", ", @{$self->{PEERS}}); }Or maybe even one like this: sub happy_birthday { my $self = shift; return ++$self->{AGE}; }Some might argue that one should go at these this way: sub exclaim { my $self = shift; return sprintf "Hi, I'm %s, age %d, working with %s", $self->name, $self->age, join(", ", $self->peers);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?