or, if you've been prudent:tie @array, 'Tie::ArrayXYZ'; tied(@array)->method(@args);
But this is a primary flaw in the design of a tied class -- the fact that there is an object behind the variable should be hidden. This means that your user should be allowed to use the extra "methods" as regular functions.$obj = tie @array, 'Tie::ArrayXYZ'; $obj->method(@args);
But how do you implement that? Well, you'll need to export "method" to the calling package, and prototype it to take the proper type as the first arg, and then do error-checking to make sure the first arg is actually tied, and that the object it is tied to inherits from your class.method(@array, @args);
Geez. Maybe that's transparent to the user, but what about the poor coder?
Enter my newest creation, which will probably appear on CPAN in the near future. It allows you to define additional methods on your tied objects as though they were ordinary ones, but then it exports them to the caller, and does all of the above, automatically. Watch:
That's all you need to do. Now, your user's code changes from:package Tie::ArrayXYZ; use Tie::Functions qw( @ changeXYZ ); # ... sub CHANGEXYZ { my ($obj, $new_xyz) = @_; $obj->{XYZ} = $new_xyz; } 1;
touse Tie::ArrayXYZ; tie @array, 'Tie::ArrayXYZ', $some_xyz; # ... tied(@array)->CHANGEXYZ($new_xyz);
Notice anything different? It looks like a regular function call, but here's what changeXYZ() looks like:use Tie::ArrayXYZ; tie @array, 'Tie::ArrayXYZ', $some_xyz; # ... changeXYZ(@array,$new_xyz);
It's dynamically generated. The name of the class, the name of the function, and the fact that we're expecting an array, are all determined from the use Tie::Functions line:sub main::changeXYZ (\@@) { my $arg = shift; my $obj = tied @$arg; Carp::croak( "First arg to main::changeXYZ must be array tied to Tie::ArrayXYZ" ) unless defined($obj) and $obj->isa("Tie::ArrayXYZ"); return $obj->CHANGEXYZ(@_); }
The variable type ($, @, %, or *) determines the prototype and dereferencing. The functions are the representation of the method names you want the user to see. Currently, they must be case-insensitively identical to the method name, and the method name must be in all caps. This explains the correlation between 'changeXYZ' on the user's side, and 'CHANGEXYZ' on the module's side. The prototype of the function created also has a '@' as the secondary term, meaning that there can be any number of arguments after the required one. There might be plans to offer a more extensible prototyping system to the coder.use Tie::Functions VARTYPE, FUNCTIONS;
I hope this seems useful to someone. Here's the code:
package Tie::Functions; use Carp; my %trans = qw( $ scalar @ array % hash * glob ); sub import { shift; my $type = shift; my $pkg = caller(0); my $ppkg = caller(1); croak "Type must be '\$', '\@', '%', '*', not '$type'." unless $type eq '$' or $type eq '@' or $type eq '%' or $type eq '* +'; eval qq[ sub ${ppkg}::$_ (\\$type\@) { my \$arg = shift; my \$obj = tied $type\$arg; Carp::croak( "First arg to ${ppkg}::$_ must be $trans{$type} tied to $pkg" ) unless defined(\$obj) and \$obj->isa("$pkg"); return \$obj->\U$_\E(\@_); } ] for @_; } 1;
_____________________________________________________
Jeff[japhy]Pinyan:
Perl,
regex,
and perl
hacker.
s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Tied variables and functions for them
by theorbtwo (Prior) on Oct 03, 2001 at 08:58 UTC | |
|
Re: Tied variables and functions for them
by pixel (Scribe) on Oct 03, 2001 at 12:22 UTC | |
|
Re: Tied variables and functions for them
by dragonchild (Archbishop) on Oct 03, 2001 at 16:55 UTC | |
by davorg (Chancellor) on Oct 03, 2001 at 17:31 UTC | |
|
Re (tilly) 1: Tied variables and functions for them
by tilly (Archbishop) on Oct 03, 2001 at 22:44 UTC | |
by dragonchild (Archbishop) on Oct 03, 2001 at 23:24 UTC |