10.3 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 explained in a moment. When you write:

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

you can generally replace it with:

 classmethod Class @args; instancemethod $instance @other; 

A typical use of this is with the new method, replacing:

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

with:

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

making 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 previous "generally" caveat? Well, if the instance is something more complicated than a simple scalar variable:

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

then you can't just swap it around like:

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

because 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. [6]

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

This means you have to write it like so:

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

And that goes from simple to uglier 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) [7] and got this interesting series of messages:

[7] Using -w should be the first step when Perl does something you don't understand. Or maybe it should be the zeroth because you should normally have -w in effect whenever you'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.

This leads us to our next strong suggestion:

Use direct object syntax at all times, except perhaps for the constructor call .

That exception acknowledges that most people write new Class .. . rather than Class->new(...) and that most of us are fine with that. 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.



Learning Perl Objects, References & Modules
Learning Perl Objects, References, and Modules
ISBN: 0596004788
EAN: 2147483647
Year: 2003
Pages: 199

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net