Subject: | Delegation of autoloaded methods does not work |
Delegation to methods that are AUTOLOADed or delegation to methods that themselves are delegated again (via Class::Delegation) fails. This is due to line #94 checking whether
$object->can($method)
- something that foils AUTOLOADing. The fix is to remove that line. I don't know whether this has further implications, but I did not find any.
I did report this bug already via email but I fear this email got lost somewhere.
The error can be found at least with the versions of Perl at my disposal:
This is perl, v5.6.1 built for MSWin32-x86-multi-thread
This is perl, v5.6.1 built for i386-linux
This is perl, v5.8.0 built for i686-linux-thread-multi
Here is a test that exploits this behaviour :
#!/usr/bin/perl -w
# Class::Delegations INIT{} block dosen't work with 5.004
require 5.006;
use vars qw( $called );
package Delegation::Base;
sub new {
my ($class) = @_;
my $self = {};
bless $self, $class;
$self;
};
sub frob {
$::called = 1;
};
package Delegation::Test::Delegator1;
use Class::Delegation
send => 'frob',
to => 'frobnicator';
sub new {
my ($class) = @_;
my $self = {
frobnicator => Delegation::Base->new(),
};
bless $self, $class;
$self;
};
package Delegation::Test::Delegator2;
use Class::Delegation
send => 'frob',
to => 'delegator1';
sub new {
my ($class) = @_;
my $self = {
delegator1 => Delegation::Test::Delegator1->new(),
};
bless $self, $class;
$self;
};
package main;
use Test::More tests => 3;
my $delegator2 = Delegation::Test::Delegator2->new();
ok( ! UNIVERSAL::can( $delegator2, "frob" ), "delegator2->frob is not autoloaded" );
eval { $delegator2->frob() };
is($@,"","Calling delegator2->frob() works");
if ($@) {
diag "This is most likely caused by a bug in Class::Delegation";
diag "Class::Delegation checks whether an object can() a method,";
diag "which prevents inherited autoloaded methods. Please change";
diag "line 94 from";
diag ' return unless eval { $target->can($as) };';
diag "to";
diag ' #return unless eval { $target->can($as) };';
};
is($called,1,"Delegation::Base->frob() was called");