Based on your edit, $A
and $B
will be used to call methods on.
So, I assume that they are singleton objects stored as class data for the base class.
If you expose them as variables, they can be easily altered and all kinds of problems can occur.
Why not use an accessor?
package Foo::Proto;
my $A;
my $B;
sub A {
return $A;
}
sub B {
return $B;
}
package Foo::Child;
our @ISA= qw(Foo::Prototype);
sub test {
my $self = shift;
$self->A->blah();
# Or if I am doing many things with A, and want to type less:
my $A = $self->A;
$A->blah();
}
package Foo::Kid;
our @ISA= qw(Foo::Prototype);
# If you will never change $A in the prototype, you could do this:
my $A = __PACKAGE__->A;
sub test {
$A->blah();
}
But all this seems like a lot of mucking about.
To solve this problem in my code I would use Moose, and then create a role to bring in A and B related methods.
my $m = Foo::Mooseling->new();
$m->test_A();
$m->test_B();
BEGIN { # This is going to be $A, I needed something to call $A->foo on.
package Thing1;
sub new { bless {}, __PACKAGE__; }
sub foo { print __PACKAGE__."::foo()\n"; }
sub blah { print __PACKAGE__."::blah()\n"; }
}
BEGIN { # This is going to be B. It is not interesting either.
package Thing2;
sub new { bless {}, __PACKAGE__; }
sub bar { print __PACKAGE__."::bar()\n"; }
sub bluh { print __PACKAGE__."::bluh()\n"; }
}
# This is the interesting part:
BEGIN { # This ROLE will provide A and B methods to any objects that include it.
package Foo::ProtoMoose;
use Moose::Role;
has 'A' => (
is => 'ro',
isa => 'Thing1',
handles => [qw( foo blah )], # Delegate calls to foo and blah for consuming object to this A.
default => sub { Thing1->new(); }, # Create a Thing1 to be A.
);
has 'B' => (
is => 'ro',
isa => 'Thing2',
handles => [qw( bar bluh )],
default => sub { Thing2->new(); },
);
}
BEGIN { # This method consumes the ProtoMoose Role.
package Foo::Mooseling;
use Moose;
with 'Foo::ProtoMoose';
sub test_A {
my $class = shift;
$class->foo;
$class->blah;
}
sub test_B {
my $class = shift;
$class->bar;
$class->bluh;
}
}
If you want Thing1 and Thing2 to be singletons, use MooseX::Singleton.