in reply to Generic/Variable/Dynamic Subroutines? (Not a redefine)
This will generate those three subs you showed (Update: see Function Templates and Method Names as Strings):
for my $meth (qw/ WriteLine Select Add /) { my $sub = sub { my $self = shift; my $it = $self->OStream->$meth($_[0]); $self->Trace(_CallerStr($it)); return $it; }; no strict 'refs'; *$meth = $sub; }
Optionally put that in a BEGIN { ... } block if you want to be able to call the subs without parens.
Here's a simple wrapper class that uses Autoloading, although autoloading can be a bit dangerous and have some caveats (e.g. the following doesn't overload UNIVERSAL methods like can, although it probably should for completeness; Update: also this example always calls the method in scalar context, although that could be changed by inspecting wantarray; plus obviously wrapper and wrapped objects have completely different classes, so isa and especially ref checks would break), so I would recommend the above solution instead. Use this like my $wrapper = Wrapper->new($object); and you should be able to call the original methods from $object on $wrapper instead. Update 2: I guess I should be more clear that the following is really just a demonstration of the (sometimes scary) power of AUTOLOADing and not something I'd recommend for wide use. You might want to look at something like around from Class::Method::Modifiers instead.
package Wrapper; use Carp; sub new { my ($class,$wrapped) = @_; return bless \$wrapped, $class; } sub AUTOLOAD { my $wrapped = shift; (my $meth = our $AUTOLOAD) =~ s/.*:://; croak "Wrapped object $$wrapped doesn't have a method $meth" unless $$wrapped->can($meth); # do stuff here my $returnval = $$wrapped->$meth(@_); # call wrapped method # and more stuff here return $returnval; } sub DESTROY {} # don't autoload DESTROY
|
---|