[ Team LiB ] |
10.3 Indirect Object NotationThe 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]
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:
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:
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. |
[ Team LiB ] |