📄 perlboot.1
字号:
Only the name of the package and the specific sound change. So can wesomehow share the definition for \f(CW\*(C`speak\*(C'\fR between the Cow and theHorse? Yes, with inheritance!.Sh "Inheriting the windpipes".IX Subsection "Inheriting the windpipes"We'll define a common subroutine package called \f(CW\*(C`Animal\*(C'\fR, with thedefinition for \f(CW\*(C`speak\*(C'\fR:.PP.Vb 6\& { package Animal;\& sub speak {\& my $class = shift;\& print "a $class goes ", $class\->sound, "!\en";\& }\& }.Ve.PPThen, for each animal, we say it \*(L"inherits\*(R" from \f(CW\*(C`Animal\*(C'\fR, alongwith the animal-specific sound:.PP.Vb 4\& { package Cow;\& @ISA = qw(Animal);\& sub sound { "moooo" }\& }.Ve.PPNote the added \f(CW@ISA\fR array. We'll get to that in a minute..PPBut what happens when we invoke \f(CW\*(C`Cow\->speak\*(C'\fR now?.PPFirst, Perl constructs the argument list. In this case, it's just\&\f(CW\*(C`Cow\*(C'\fR. Then Perl looks for \f(CW\*(C`Cow::speak\*(C'\fR. But that's not there, soPerl checks for the inheritance array \f(CW@Cow::ISA\fR. It's there,and contains the single name \f(CW\*(C`Animal\*(C'\fR..PPPerl next checks for \f(CW\*(C`speak\*(C'\fR inside \f(CW\*(C`Animal\*(C'\fR instead, as in\&\f(CW\*(C`Animal::speak\*(C'\fR. And that's found, so Perl invokes that subroutinewith the already frozen argument list..PPInside the \f(CW\*(C`Animal::speak\*(C'\fR subroutine, \f(CW$class\fR becomes \f(CW\*(C`Cow\*(C'\fR (thefirst argument). So when we get to the step of invoking\&\f(CW\*(C`$class\->sound\*(C'\fR, it'll be looking for \f(CW\*(C`Cow\->sound\*(C'\fR, whichgets it on the first try without looking at \f(CW@ISA\fR. Success!.ie n .Sh "A few notes about @ISA".el .Sh "A few notes about \f(CW@ISA\fP".IX Subsection "A few notes about @ISA"This magical \f(CW@ISA\fR variable (pronounced \*(L"is a\*(R" not \*(L"ice-uh\*(R"), hasdeclared that \f(CW\*(C`Cow\*(C'\fR \*(L"is a\*(R" \f(CW\*(C`Animal\*(C'\fR. Note that it's an array,not a simple single value, because on rare occasions, it makes senseto have more than one parent class searched for the missing methods..PPIf \f(CW\*(C`Animal\*(C'\fR also had an \f(CW@ISA\fR, then we'd check there too. Thesearch is recursive, depth-first, left-to-right in each \f(CW@ISA\fR bydefault (see mro for alternatives). Typically, each \f(CW@ISA\fR hasonly one element (multiple elements means multiple inheritance andmultiple headaches), so we get a nice tree of inheritance..PPWhen we turn on \f(CW\*(C`use strict\*(C'\fR, we'll get complaints on \f(CW@ISA\fR, sinceit's not a variable containing an explicit package name, nor is it alexical (\*(L"my\*(R") variable. We can't make it a lexical variable though(it has to belong to the package to be found by the inheritance mechanism),so there's a couple of straightforward ways to handle that..PPThe easiest is to just spell the package name out:.PP.Vb 1\& @Cow::ISA = qw(Animal);.Ve.PPOr allow it as an implicitly named package variable:.PP.Vb 3\& package Cow;\& use vars qw(@ISA);\& @ISA = qw(Animal);.Ve.PPIf you're bringing in the class from outside, via an object-orientedmodule, you change:.PP.Vb 4\& package Cow;\& use Animal;\& use vars qw(@ISA);\& @ISA = qw(Animal);.Ve.PPinto just:.PP.Vb 2\& package Cow;\& use base qw(Animal);.Ve.PPAnd that's pretty darn compact..Sh "Overriding the methods".IX Subsection "Overriding the methods"Let's add a mouse, which can barely be heard:.PP.Vb 10\& # Animal package from before\& { package Mouse;\& @ISA = qw(Animal);\& sub sound { "squeak" }\& sub speak {\& my $class = shift;\& print "a $class goes ", $class\->sound, "!\en";\& print "[but you can barely hear it!]\en";\& }\& }\&\& Mouse\->speak;.Ve.PPwhich results in:.PP.Vb 2\& a Mouse goes squeak!\& [but you can barely hear it!].Ve.PPHere, \f(CW\*(C`Mouse\*(C'\fR has its own speaking routine, so \f(CW\*(C`Mouse\->speak\*(C'\fRdoesn't immediately invoke \f(CW\*(C`Animal\->speak\*(C'\fR. This is known as\&\*(L"overriding\*(R". In fact, we didn't even need to say that a \f(CW\*(C`Mouse\*(C'\fR wasan \f(CW\*(C`Animal\*(C'\fR at all, since all of the methods needed for \f(CW\*(C`speak\*(C'\fR arecompletely defined with \f(CW\*(C`Mouse\*(C'\fR..PPBut we've now duplicated some of the code from \f(CW\*(C`Animal\->speak\*(C'\fR,and this can once again be a maintenance headache. So, can we avoidthat? Can we say somehow that a \f(CW\*(C`Mouse\*(C'\fR does everything any other\&\f(CW\*(C`Animal\*(C'\fR does, but add in the extra comment? Sure!.PPFirst, we can invoke the \f(CW\*(C`Animal::speak\*(C'\fR method directly:.PP.Vb 10\& # Animal package from before\& { package Mouse;\& @ISA = qw(Animal);\& sub sound { "squeak" }\& sub speak {\& my $class = shift;\& Animal::speak($class);\& print "[but you can barely hear it!]\en";\& }\& }.Ve.PPNote that we have to include the \f(CW$class\fR parameter (almost surelythe value of \f(CW"Mouse"\fR) as the first parameter to \f(CW\*(C`Animal::speak\*(C'\fR,since we've stopped using the method arrow. Why did we stop? Well,if we invoke \f(CW\*(C`Animal\->speak\*(C'\fR there, the first parameter to themethod will be \f(CW"Animal"\fR not \f(CW"Mouse"\fR, and when time comes for itto call for the \f(CW\*(C`sound\*(C'\fR, it won't have the right class to come backto this package..PPInvoking \f(CW\*(C`Animal::speak\*(C'\fR directly is a mess, however. What if\&\f(CW\*(C`Animal::speak\*(C'\fR didn't exist before, and was being inherited from aclass mentioned in \f(CW@Animal::ISA\fR? Because we are no longer usingthe method arrow, we get one and only one chance to hit the rightsubroutine..PPAlso note that the \f(CW\*(C`Animal\*(C'\fR classname is now hardwired into thesubroutine selection. This is a mess if someone maintains the code,changing \f(CW@ISA\fR for \f(CW\*(C`Mouse\*(C'\fR and didn't notice \f(CW\*(C`Animal\*(C'\fR there in\&\f(CW\*(C`speak\*(C'\fR. So, this is probably not the right way to go..Sh "Starting the search from a different place".IX Subsection "Starting the search from a different place"A better solution is to tell Perl to search from a higher placein the inheritance chain:.PP.Vb 9\& # same Animal as before\& { package Mouse;\& # same @ISA, &sound as before\& sub speak {\& my $class = shift;\& $class\->Animal::speak;\& print "[but you can barely hear it!]\en";\& }\& }.Ve.PPAhh. This works. Using this syntax, we start with \f(CW\*(C`Animal\*(C'\fR to find\&\f(CW\*(C`speak\*(C'\fR, and use all of \f(CW\*(C`Animal\*(C'\fR's inheritance chain if not foundimmediately. And yet the first parameter will be \f(CW$class\fR, so thefound \f(CW\*(C`speak\*(C'\fR method will get \f(CW\*(C`Mouse\*(C'\fR as its first entry, andeventually work its way back to \f(CW\*(C`Mouse::sound\*(C'\fR for the details..PPBut this isn't the best solution. We still have to keep the \f(CW@ISA\fRand the initial search package coordinated. Worse, if \f(CW\*(C`Mouse\*(C'\fR hadmultiple entries in \f(CW@ISA\fR, we wouldn't necessarily know which onehad actually defined \f(CW\*(C`speak\*(C'\fR. So, is there an even better way?.Sh "The \s-1SUPER\s0 way of doing things".IX Subsection "The SUPER way of doing things"By changing the \f(CW\*(C`Animal\*(C'\fR class to the \f(CW\*(C`SUPER\*(C'\fR class in thatinvocation, we get a search of all of our super classes (classeslisted in \f(CW@ISA\fR) automatically:.PP.Vb 9\& # same Animal as before\& { package Mouse;\& # same @ISA, &sound as before\& sub speak {\& my $class = shift;\& $class\->SUPER::speak;\& print "[but you can barely hear it!]\en";\& }\& }.Ve.PPSo, \f(CW\*(C`SUPER::speak\*(C'\fR means look in the current package's \f(CW@ISA\fR for\&\f(CW\*(C`speak\*(C'\fR, invoking the first one found. Note that it does \fInot\fR look inthe \f(CW@ISA\fR of \f(CW$class\fR..Sh "Where we're at so far...".IX Subsection "Where we're at so far..."So far, we've seen the method arrow syntax:.PP.Vb 1\& Class\->method(@args);.Ve.PPor the equivalent:.PP.Vb 2\& $a = "Class";\& $a\->method(@args);.Ve.PPwhich constructs an argument list of:.PP.Vb 1\& ("Class", @args).Ve.PPand attempts to invoke.PP.Vb 1\& Class::method("Class", @Args);.Ve.PPHowever, if \f(CW\*(C`Class::method\*(C'\fR is not found, then \f(CW@Class::ISA\fR is examined(recursively) to locate a package that does indeed contain \f(CW\*(C`method\*(C'\fR,and that subroutine is invoked instead..PPUsing this simple syntax, we have class methods, (multiple)inheritance, overriding, and extending. Using just what we've seen sofar, we've been able to factor out common code, and provide a nice wayto reuse implementations with variations. This is at the core of whatobjects provide, but objects also provide instance data, which wehaven't even begun to cover..Sh "A horse is a horse, of course of course \*(-- or is it?".IX Subsection "A horse is a horse, of course of course or is it?"Let's start with the code for the \f(CW\*(C`Animal\*(C'\fR classand the \f(CW\*(C`Horse\*(C'\fR class:.PP.Vb 10\& { package Animal;\& sub speak {\& my $class = shift;\& print "a $class goes ", $class\->sound, "!\en";\& }\& }\& { package Horse;\& @ISA = qw(Animal);\& sub sound { "neigh" }\& }.Ve.PPThis lets us invoke \f(CW\*(C`Horse\->speak\*(C'\fR to ripple upward to\&\f(CW\*(C`Animal::speak\*(C'\fR, calling back to \f(CW\*(C`Horse::sound\*(C'\fR to get the specificsound, and the output of:.PP.Vb 1\& a Horse goes neigh!.Ve.PPBut all of our Horse objects would have to be absolutely identical.If I add a subroutine, all horses automatically share it. That'sgreat for making horses the same, but how do we capture thedistinctions about an individual horse? For example, suppose I wantto give my first horse a name. There's got to be a way to keep itsname separate from the other horses..PPWe can do that by drawing a new distinction, called an \*(L"instance\*(R".An \*(L"instance\*(R" is generally created by a class. In Perl, any referencecan be an instance, so let's start with the simplest referencethat can hold a horse's name: a scalar reference..PP.Vb 2\& my $name = "Mr. Ed";\& my $talking = \e$name;.Ve.PPSo now \f(CW$talking\fR is a reference to what will be the instance-specificdata (the name). The final step in turning this into a real instanceis with a special operator called \f(CW\*(C`bless\*(C'\fR:.PP.Vb 1\& bless $talking, Horse;.Ve.PPThis operator stores information about the package named \f(CW\*(C`Horse\*(C'\fR intothe thing pointed at by the reference. At this point, we say\&\f(CW$talking\fR is an instance of \f(CW\*(C`Horse\*(C'\fR. That is, it's a specifichorse. The reference is otherwise unchanged, and can still be usedwith traditional dereferencing operators..Sh "Invoking an instance method".IX Subsection "Invoking an instance method"The method arrow can be used on instances, as well as names ofpackages (classes). So, let's get the sound that \f(CW$talking\fR makes:.PP.Vb 1\& my $noise = $talking\->sound;.Ve.PPTo invoke \f(CW\*(C`sound\*(C'\fR, Perl first notes that \f(CW$talking\fR is a blessedreference (and thus an instance). It then constructs an argumentlist, in this case from just \f(CW\*(C`($talking)\*(C'\fR. (Later we'll see thatarguments will take their place following the instance variable,just like with classes.).PPNow for the fun part: Perl takes the class in which the instance wasblessed, in this case \f(CW\*(C`Horse\*(C'\fR, and uses that to locate the subroutineto invoke the method. In this case, \f(CW\*(C`Horse::sound\*(C'\fR is found directly(without using inheritance), yielding the final subroutine invocation:.PP.Vb 1\& Horse::sound($talking).Ve.PPNote that the first parameter here is still the instance, not the nameof the class as before. We'll get \f(CW\*(C`neigh\*(C'\fR as the return value, andthat'll end up as the \f(CW$noise\fR variable above..PPIf Horse::sound had not been found, we'd be wandering up the\&\f(CW@Horse::ISA\fR list to try to find the method in one of thesuperclasses, just as for a class method. The only difference betweena class method and an instance method is whether the first parameteris an instance (a blessed reference) or a class name (a string)..Sh "Accessing the instance data".IX Subsection "Accessing the instance data"Because we get the instance as the first parameter, we can now accessthe instance-specific data. In this case, let's add a way to get atthe name:.PP.Vb 8\& { package Horse;\& @ISA = qw(Animal);\& sub sound { "neigh" }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -