return $self;
}
-Or if you expect people to call not just C<CLASS-E<gt>new()> but also
-C<$obj-E<gt>new()>, then use something like this. The initialize()
+Or if you expect people to call not just C<< CLASS->new() >> but also
+C<< $obj->new() >>, then use something like this. The initialize()
method used will be of whatever $class we blessed the
object into:
If none of that works, Perl finally gives up and complains.
+If you want to stop the AUTOLOAD inheritance say simply
+
+ sub AUTOLOAD;
+
+and the call will die using the name of the sub being called.
+
Perl classes do method inheritance only. Data inheritance is left up
to the class itself. By and large, this is not a problem in Perl,
because most classes model the attributes of their object using an
=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
-
- print STDERR "help!!!\n";
-
-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.
-
- $fred = find Critter "Fred";
- display $fred 'Height', 'Weight';
-
-These could be combined into one statement by using a BLOCK in the
-indirect object slot:
+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:
- display {find Critter "Fred"} 'Height', 'Weight';
+ my $fred = Critter->find("Fred");
+ $fred->display("Height", "Weight");
-For C++ fans, there's also a syntax using -E<gt> notation that does exactly
-the same thing. The parentheses are required if there are any arguments.
+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 = Critter->find("Fred");
- $fred->display('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:
-or in one statement,
+ my $fred = Critter::find("Critter", "Fred");
+ Critter::display($fred, "Height", "Weight");
- Critter->find("Fred")->display('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.
-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
+If you need to, you I<can> force Perl to start looking in some other package:
- new Critter ('Barney', 1.5, 70)
+ my $barney = MyCritter->Critter::find("Barney");
+ $barney->Critter::display("Height", "Weight");
-are assumed to surround ALL the arguments of the method call, regardless
-of what comes after. Saying
+Here C<MyCritter> is presumably a subclass of C<Critter> 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>.
- new Critter ('Bam' x 2), 1.4, 45
+As a special case of the above, you may use the C<SUPER> pseudo-class to
+tell Perl to start looking for the method in the packages named in the
+current class's C<@ISA> list.
-would be equivalent to
+ package MyCritter;
+ use base 'Critter'; # sets @MyCritter::ISA = ('Critter');
- 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<Package::> 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)
+ sub display {
+ my ($self, @args) = @_;
+ $self->SUPER::display("Name", @args);
+ }
-For more reasons why the indirect object syntax is ambiguous, see
-L<"WARNING"> below.
+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:
-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:
+ Critter->find("Fred")->display("Height", "Weight");
- $fred = MyCritter::find("Critter", "Fred");
- MyCritter::display($fred, 'Height', 'Weight');
+and so is the following:
-Unlike method calls, function calls don't consider inheritance. If you wish
-merely to specify that Perl should I<START> looking for a method in a
-particular package, use an ordinary method call, but qualify the method
-name with the package like this:
+ my $fred = (reverse "rettirC")->find(reverse "derF");
- $fred = Critter->MyCritter::find("Fred");
- $fred->MyCritter::display('Height', 'Weight');
+=head2 Indirect Object Syntax
-If you're trying to control where the method search begins I<and> 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:
+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:
- $self->SUPER::display('Height', 'Weight');
+ print STDERR "help!!!\n";
-Please note that the C<SUPER::> construct is meaningful I<only> within the
-class.
+The same syntax can be used to call either object or class methods.
-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.
+ my $fred = find Critter "Fred";
+ display $fred "Height", "Weight";
- $method = $fast ? "findfirst" : "findbest";
- $fred->$method(@args); # call by name
+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.
- if ($coderef = $fred->can($parent . "::findbest")) {
- $self->$coderef(@args); # call by coderef
- }
+But what if there are no arguments? In that case, Perl must guess what
+you want. Even worse, it must make that guess I<at compile time>.
+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.
-=head2 WARNING
+For example, a call to a method C<new> in indirect notation -- as C++
+programmers are wont to make -- can be miscompiled into a subroutine
+call if there's already a C<new> function in scope. You'd end up
+calling the current package's C<new> as a subroutine, rather than the
+desired class's method. The compiler tries to cheat by remembering
+bareword C<require>s, 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.
-While indirect object syntax may well be appealing to English speakers and
-to C++ programmers, be not seduced! It suffers from two grave problems.
-
-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<print> and C<printf>.) 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<print> and C<printf>.)
+This can lead to horribly confusing precedence problems, as in these
+next two lines:
move $obj->{FIELD}; # probably wrong!
move $ary[$i]; # probably wrong!
Those actually parse as the very surprising:
$obj->move->{FIELD}; # Well, lookee here
- $ary->move->[$i]; # Didn't expect this one, eh?
+ $ary->move([$i]); # Didn't expect this one, eh?
Rather than what you might have expected:
$obj->{FIELD}->move(); # You should be so lucky.
$ary[$i]->move; # Yeah, sure.
-The left side of ``-E<gt>'' 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<at
-compile time> whether C<name> and C<move> 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<new>
-in indirect notation--as C++ programmers are so wont to do--can
-be miscompiled into a subroutine call if there's already a C<new>
-function in scope. You'd end up calling the current package's C<new>
-as a subroutine, rather than the desired class's method. The compiler
-tries to cheat by remembering bareword C<require>s, 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<-E<gt>>'' 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<move> in the current package. B<The C<< -> >>
+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
C<isa> returns I<true> if its object is blessed into a subclass of C<CLASS>
-C<isa> 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
+You can also call C<UNIVERSAL::isa> 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
- use UNIVERSAL qw(isa);
-
- 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<can> checks to see if its object has a method called C<METHOD>,
if it does then a reference to the sub is returned, if it does not then
I<undef> is returned.
+C<UNIVERSAL::can> can also be called as a subroutine with two arguments.
+It'll always return I<undef> 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<blessed> function of Scalar::Util:
+
+ use Scalar::Util 'blessed';
+
+ my $blessing = blessed $suspected_object;
+
+C<blessed> returns the name of the package the argument has been
+blessed into, or C<undef>.
+
=item VERSION( [NEED] )
C<VERSION> returns the version number of the class (package). If the
You may add other methods to the UNIVERSAL class via Perl or XS code.
You do not need to C<use UNIVERSAL> to make these methods
-available to your program. This is necessary only if you wish to
-have C<isa> available as a plain subroutine in the current package.
+available to your program (and you should not do so).
=head2 Destructors
is greater than 0. You can test the higher levels of global destruction
by setting the PERL_DESTRUCT_LEVEL environment variable, presuming
C<-DDEBUGGING> was enabled during perl build time.
+See L<perlhack/PERL_DESTRUCT_LEVEL> for more information.
A more complete garbage collection strategy will be implemented
at a future date.
=head1 SEE ALSO
-A kinder, gentler tutorial on object-oriented programming in Perl
-can be found in L<perltoot> and L<perltootc>. You should also check
-out L<perlbot> for other object tricks, traps, and tips, as well
-as L<perlmodlib> for some style guides on constructing both modules
-and classes.
+A kinder, gentler tutorial on object-oriented programming in Perl can
+be found in L<perltoot>, L<perlboot> and L<perltootc>. You should
+also check out L<perlbot> for other object tricks, traps, and tips, as
+well as L<perlmodlib> for some style guides on constructing both
+modules and classes.