X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pod%2Fperlobj.pod;h=e466dc7dd7f3e20c9454820effe45adbc9fdbc4a;hb=4521542890c02b2ddcb4a39429066bc380e4e5e7;hp=53009c5eb2566228b4160a62d2a9dc76b4547131;hpb=64cea5fd15e12c83d54ce3dfffefd610e449e8c6;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pod/perlobj.pod b/pod/perlobj.pod index 53009c5..e466dc7 100644 --- a/pod/perlobj.pod +++ b/pod/perlobj.pod @@ -227,117 +227,102 @@ and then uses that as an ordinary reference. =head2 Method Invocation -There are two ways to invoke a method, one of which you're already -familiar with, and the other of which will look familiar. Perl 4 -already had an "indirect object" syntax that you use when you say +For various historical and other reasons, Perl offers two equivalent +ways to write a method call. The simpler and more common way is to use +the arrow notation: - print STDERR "help!!!\n"; + my $fred = Critter->find("Fred"); + $fred->display("Height", "Weight"); -This same syntax can be used to call either class or instance methods. -We'll use the two methods defined above, the class method to lookup -an object reference and the instance method to print out its attributes. +You should already be familiar with the use of the C<< -> >> operator with +references. In fact, since C<$fred> above is a reference to an object, +you could think of the method call as just another form of +dereferencing. - $fred = find Critter "Fred"; - display $fred 'Height', 'Weight'; +Whatever is on the left side of the arrow, whether a reference or a +class name, is passed to the method subroutine as its first argument. +So the above code is mostly equivalent to: -These could be combined into one statement by using a BLOCK in the -indirect object slot: + my $fred = Critter::find("Critter", "Fred"); + Critter::display($fred, "Height", "Weight"); - display {find Critter "Fred"} 'Height', 'Weight'; +How does Perl know which package the subroutine is in? By looking at +the left side of the arrow, which must be either a package name or a +reference to an object, i.e. something that has been blessed to a +package. Either way, that's the package where Perl starts looking. If +that package has no subroutine with that name, Perl starts looking for +it in any base classes of that package, and so on. -For C++ fans, there's also a syntax using -> notation that does exactly -the same thing. The parentheses are required if there are any arguments. +If you need to, you I force Perl to start looking in some other package: - $fred = Critter->find("Fred"); - $fred->display('Height', 'Weight'); + my $barney = MyCritter->Critter::find("Barney"); + $barney->Critter::display("Height", "Weight"); -or in one statement, +Here C is presumably a subclass of C that defines +its own versions of find() and display(). We haven't specified what +those methods do, but that doesn't matter above since we've forced Perl +to start looking for the subroutines in C. - Critter->find("Fred")->display('Height', 'Weight'); +As a special case of the above, you may use the C pseudo-class to +tell Perl to start looking for the method in the packages named in the +current class's C<@ISA> list. -There are times when one syntax is more readable, and times when the -other syntax is more readable. The indirect object syntax is less -cluttered, but it has the same ambiguity as ordinary list operators. -Indirect object method calls are usually parsed using the same rule as list -operators: "If it looks like a function, it is a function". (Presuming -for the moment that you think two words in a row can look like a -function name. C++ programmers seem to think so with some regularity, -especially when the first word is "new".) Thus, the parentheses of + package MyCritter; + use base 'Critter'; # sets @MyCritter::ISA = ('Critter'); - new Critter ('Barney', 1.5, 70) - -are assumed to surround ALL the arguments of the method call, regardless -of what comes after. Saying - - new Critter ('Bam' x 2), 1.4, 45 - -would be equivalent to - - Critter->new('Bam' x 2), 1.4, 45 - -which is unlikely to do what you want. Confusingly, however, this -rule applies only when the indirect object is a bareword package name, -not when it's a scalar, a BLOCK, or a C qualified package name. -In those cases, the arguments are parsed in the same way as an -indirect object list operator like print, so - - new Critter:: ('Bam' x 2), 1.4, 45 - -is the same as - - Critter::->new(('Bam' x 2), 1.4, 45) - -For more reasons why the indirect object syntax is ambiguous, see -L<"WARNING"> below. + sub display { + my ($self, @args) = @_; + $self->SUPER::display("Name", @args); + } -There are times when you wish to specify which class's method to use. -Here you can call your method as an ordinary subroutine -call, being sure to pass the requisite first argument explicitly: +Instead of a class name or an object reference, you can also use any +expression that returns either of those on the left side of the arrow. +So the following statement is valid: - $fred = MyCritter::find("Critter", "Fred"); - MyCritter::display($fred, 'Height', 'Weight'); + Critter->find("Fred")->display("Height", "Weight"); -Unlike method calls, function calls don't consider inheritance. If you wish -merely to specify that Perl should I looking for a method in a -particular package, use an ordinary method call, but qualify the method -name with the package like this: +and so is the following: - $fred = Critter->MyCritter::find("Fred"); - $fred->MyCritter::display('Height', 'Weight'); + my $fred = (reverse "rettirC")->find(reverse "derF"); -If you're trying to control where the method search begins I you're -executing in the class itself, then you may use the SUPER pseudo class, -which says to start looking in your base class's @ISA list without having -to name it explicitly: +=head2 Indirect Object Syntax - $self->SUPER::display('Height', 'Weight'); +The other way to invoke a method is by using the so-called "indirect +object" notation. This syntax was available in Perl 4 long before +objects were introduced, and is still used with filehandles like this: -Please note that the C construct is meaningful I within the -class. + print STDERR "help!!!\n"; -Sometimes you want to call a method when you don't know the method name -ahead of time. You can use the arrow form, replacing the method name -with a simple scalar variable containing the method name or a -reference to the function. +The same syntax can be used to call either object or class methods. - $method = $fast ? "findfirst" : "findbest"; - $fred->$method(@args); # call by name + my $fred = find Critter "Fred"; + display $fred "Height", "Weight"; - if ($coderef = $fred->can($parent . "::findbest")) { - $self->$coderef(@args); # call by coderef - } +Notice that there is no comma between the object or class name and the +parameters. This is how Perl can tell you want an indirect method call +instead of an ordinary subroutine call. -=head2 WARNING +But what if there are no arguments? In that case, Perl must guess what +you want. Even worse, it must make that guess I. +Usually Perl gets it right, but when it doesn't you get a function +call compiled as a method, or vice versa. This can introduce subtle bugs +that are hard to detect. -While indirect object syntax may well be appealing to English speakers and -to C++ programmers, be not seduced! It suffers from two grave problems. +For example, a call to a method C in indirect notation -- as C++ +programmers are wont to make -- can be miscompiled into a subroutine +call if there's already a C function in scope. You'd end up +calling the current package's C as a subroutine, rather than the +desired class's method. The compiler tries to cheat by remembering +bareword Cs, but the grief when it messes up just isn't worth the +years of debugging it will take you to track down such subtle bugs. -The first problem is that an indirect object is limited to a name, -a scalar variable, or a block, because it would have to do too much -lookahead otherwise, just like any other postfix dereference in the -language. (These are the same quirky rules as are used for the filehandle -slot in functions like C and C.) This can lead to horribly -confusing precedence problems, as in these next two lines: +There is another problem with this syntax: the indirect object is +limited to a name, a scalar variable, or a block, because it would have +to do too much lookahead otherwise, just like any other postfix +dereference in the language. (These are the same quirky rules as are +used for the filehandle slot in functions like C and C.) +This can lead to horribly confusing precedence problems, as in these +next two lines: move $obj->{FIELD}; # probably wrong! move $ary[$i]; # probably wrong! @@ -352,24 +337,18 @@ Rather than what you might have expected: $obj->{FIELD}->move(); # You should be so lucky. $ary[$i]->move; # Yeah, sure. -The left side of ``->'' is not so limited, because it's an infix operator, -not a postfix operator. - -As if that weren't bad enough, think about this: Perl must guess I whether C and C above are functions or methods. -Usually Perl gets it right, but when it doesn't it, you get a function -call compiled as a method, or vice versa. This can introduce subtle -bugs that are hard to unravel. For example, calling a method C -in indirect notation--as C++ programmers are so wont to do--can -be miscompiled into a subroutine call if there's already a C -function in scope. You'd end up calling the current package's C -as a subroutine, rather than the desired class's method. The compiler -tries to cheat by remembering bareword Cs, but the grief if it -messes up just isn't worth the years of debugging it would likely take -you to track such subtle bugs down. - -The infix arrow notation using ``C<< -> >>'' doesn't suffer from either -of these disturbing ambiguities, so we recommend you use it exclusively. +To get the correct behavior with indirect object syntax, you would have +to use a block around the indirect object: + + move {$obj->{FIELD}}; + move {$ary[$i]}; + +Even then, you still have the same potential problem if there happens to +be a function named C in the current package. B >> +notation suffers from neither of these disturbing ambiguities, so we +recommend you use it exclusively.> However, you may still end up having +to read code using the indirect object notation, so it's important to be +familiar with it. =head2 Default UNIVERSAL methods @@ -382,21 +361,41 @@ are inherited by all other classes: C returns I if its object is blessed into a subclass of C -C is also exportable and can be called as a sub with two arguments. This -allows the ability to check what a reference points to. Example - - use UNIVERSAL qw(isa); +You can also call C as a subroutine with two arguments. +The first does not need to be an object or even a reference. This +allows you to check what a reference points to, or whether +something is a reference of a given type. Example - if(isa($ref, 'ARRAY')) { + if(UNIVERSAL::isa($ref, 'ARRAY')) { #... } +To determine if a reference is a blessed object, you can write + + print "It's an object\n" if UNIVERSAL::isa($val, 'UNIVERSAL'); + =item can(METHOD) C checks to see if its object has a method called C, if it does then a reference to the sub is returned, if it does not then I is returned. +C can also be called as a subroutine with two arguments. +It'll always return I if its first argument isn't an object or a +class name. So here's another way to check if a reference is a +blessed object + + print "It's still an object\n" if UNIVERSAL::can($val, 'can'); + +You can also use the C function of Scalar::Util: + + use Scalar::Util 'blessed'; + + my $blessing = blessed $suspected_object; + +C returns the name of the package the argument has been +blessed into, or C. + =item VERSION( [NEED] ) C returns the version number of the class (package). If the @@ -418,8 +417,7 @@ strange effects if the Perl code dynamically changes @ISA in any package. You may add other methods to the UNIVERSAL class via Perl or XS code. You do not need to C to make these methods -available to your program. This is necessary only if you wish to -have C available as a plain subroutine in the current package. +available to your program (and you should not do so). =head2 Destructors