Документация
HTML CSS PHP PERL другое

Section 13.4.  Indirect Object Notation

 
Previous
Table of Contents
Next

13.4. Indirect Object Notation

The arrow syntax used to invoke a method is sometimes called the direct object syntax because there's also the indirect object syntax, also known as the "only works sometimes" syntax, for reasons we explain in a moment. We can generally replace what we'd write with the arrow notation:

Class->class_method(@args);
$instance->instance_method(@other);

with the method name preceding the class name and the arguments at the end.

classmethod Class @args;
instancemethod $instance @other;

This idiom was much more prevalent in the earlier days of Perl 5, and we're still trying to eradicate it from the world. We wish that we didn't have to cover it here (if you don't know about it, you can't use it), but it sticks around in otherwise good code, so you need to know what is going on. You'll typically see this with the new method where module authors replace the arrow syntax:

my $obj = Some::Class->new(@constructor_params);

with something that reads more like English:

my $obj = new Some::Class @constructor_params;

which makes the C++ people feel right at home. Of course, in Perl, there's nothing special about the name new, but at least the syntax is hauntingly familiar.

Why the "generally" caveat on when you can replace the arrow syntax with indirect object syntax? Well, if the instance is something more complicated than a simple scalar variable:

$somehash->{$somekey}->[42]->instance_method(@parms);

then we can't just swap it around to the indirect notation:

instance_method $somehash->{$somekey}->[42] @parms;

The only things acceptable to indirect object syntax are a bareword (e.g., a class name), a simple scalar variable, or braces denoting a block returning either a blessed reference or a classname.[*] This means we have to write it like so:

[*] Astute readers will note that these are the same rules as for an indirect filehandle syntax, which indirect object syntax directly mirrors, as well as the rules for specifying a reference to be dereferenced.

instance_method { $somehash->{$somekey}->[42] } @parms;

And that goes from simple to ugly in one step. There's another downside: ambiguous parsing. When we developed the classroom materials concerning indirect object references, we wrote:

my $cow = Cow->named('Bessie');
print name $cow, " eats.\n";

because we were thinking about the indirect object equivalents for:

my $cow = Cow->named('Bessie');
print $cow->name, " eats.\n";

However, the latter works; the former doesn't. We were getting no output. Finally, we enabled warnings (via -w on the command line)[Section 13.4.  Indirect Object Notation] and got this interesting series of messages:

[Section 13.4.  Indirect Object Notation] Using -w should be the first step when Perl does something we don't understand. Or maybe it should be the zeroth, because we should normally have -w in effect whenever we're developing code.

Unquoted string "name" may clash with future reserved word at ./foo line 92.
Name "main::name" used only once: possible typo at ./foo line 92.
print(  ) on unopened filehandle name at ./foo line 92.

Ahh, so that line was being parsed as:

print name ($cow, " eats.\n");

In other words, print the list of items to the filehandle named name. That's clearly not what we wanted, so we had to add additional syntax to disambiguate the call.[Section 13.4.  Indirect Object Notation]

[Section 13.4.  Indirect Object Notation] The ambiguity shows up because print( ) itself is a method called on the filehandle. You're probably used to thinking of it as a function, but remember that missing comma after the filehandle. It looks just like our indirect object calling syntax, because it is.

This leads us to our next strong suggestion: Use direct object syntax at all times.

We realize, though, that people write new Class ... rather than Class->new(...) and that most of us are fine with that. Older modules preferred that notation in their examples, and once you write it that way, you tend to keep doing it that way. However, there are circumstances in which even that can lead to ambiguity (e.g., when a subroutine named new has been seen, and the class name itself has not been seen as a package). When in doubt, ignore indirect object syntax. Your maintenance programmer will thank you.


Previous
Table of Contents
Next
© 2000- NIV