Here a proof of concept exporting AUTOLOAD and a package var $WITH.
Autoload tries then to call any missing sub via $WITH->sub
$WITH can be easily localized to scope the effects.
More sophisticated configurations like importing only dedicated methods
or methods from different objects could be achieved by allowing $WITH to hold array
or hashes or even be tied or blessed into a config object or all off the former.
use strict;
use warnings;
use Carp;
=head1 Method::Load
Exports an AUTOLOAD routine and a package var $WITH which holds an obj
+ect.
Any unknown calls 'name' will trigger $WITH->name();
A clean implementation should check if $WITH->can(name) is missing
If an older AUTOLOAD already exists, delegate there
otherwise report error from users package.
=cut
package Method::Load;
use Data::Dump qw/pp dd/;
BEGIN { $INC{"Method/Load.pm"} = 1; } # hack: already required
use vars qw/$AUTOLOAD/;
sub import {
my $import_pkg = (caller)[0];
no strict 'refs';
my $with;
*{"${import_pkg}::WITH"} = \$with;
*{"${import_pkg}::AUTOLOAD"}=\&autoload;
}
sub autoload {
my ($pkg,$sub) = split /::/, $AUTOLOAD;
#warn "AUTOLOAD: ", pp [$pkg,$sub ];
my $obj;
{
no strict 'refs';
$obj = ${"${pkg}::WITH"};
}
if (1) {
$obj->$sub(@_);
} else { # hide autoload from caller-ch
+ain
my $c_ref = $obj->can($sub);
unshift @_,$obj;
goto &$c_ref;
}
}
=head1 Demo classes
=cut
package Delegate::Bar;
use Data::Dump qw/pp dd/;
sub bar {
#warn pp [@_];
my ($self,@args) = @_;
Carp::cluck pp [$self->{args},@args];
}
sub new {
my ($class,@args) =@_;
return bless {args => \@args}, $class;
}
package Delegate::Foo;
use Data::Dump qw/pp dd/;
sub foo {
#warn pp [@_];
my ($self,@args) = @_;
Carp::cluck pp [$self->{args},@args];
}
sub new {
my ($class,@args) =@_;
return bless {args => \@args}, $class;
}
=head1 Proof Of Concept
=cut
package Test;
use Method::Load;
my $obj= Delegate::Foo->new("is foo");
$obj->foo(0);
$WITH = $obj; # set globally
foo(1);
{
local $WITH = Delegate::Bar->new("is bar");
bar(2);
}
foo(3);
bar(4); # fails
OUTPUT:
[["is foo"], 0] at d:/exp/t_Method_Load.pl line 77.
Delegate::Foo::foo(Delegate::Foo=HASH(0x2dbc388), 0) called at d:/
+exp/t_Method_Load.pl line 100
[["is foo"], 1] at d:/exp/t_Method_Load.pl line 77.
Delegate::Foo::foo(Delegate::Foo=HASH(0x2dbc388), 1) called at d:/
+exp/t_Method_Load.pl line 42
Method::Load::autoload(1) called at d:/exp/t_Method_Load.pl line 1
+04
[["is bar"], 2] at d:/exp/t_Method_Load.pl line 63.
Delegate::Bar::bar(Delegate::Bar=HASH(0x4574b10), 2) called at d:/
+exp/t_Method_Load.pl line 42
Method::Load::autoload(2) called at d:/exp/t_Method_Load.pl line 1
+09
[["is foo"], 3] at d:/exp/t_Method_Load.pl line 77.
Delegate::Foo::foo(Delegate::Foo=HASH(0x2dbc388), 3) called at d:/
+exp/t_Method_Load.pl line 42
Method::Load::autoload(3) called at d:/exp/t_Method_Load.pl line 1
+12
Can't locate object method "bar" via package "Delegate::Foo" at d:/exp
+/t_Method_Load.pl line 42.
|