It obviously doesn't work quite how you're thinking. One of the problems is that package does not accept the namespace as a dynamic argument. The namespace must be a hard-coded string of characters. However, all is not lost. You can have everything you want, just not the way you're doing it:
package My;
use strict;
use warnings;
my $pkg_sub = __PACKAGE__ . '::A';
# some methods for package My...
{
no strict 'refs';
*{$pkg_sub . '::new'} = sub {
my $class = shift;
return bless {ref($_[0]) ? %{$_[0]} : @_}, $class;
};
*{$pkg_sub . '::greet' } = sub { print 'Hello ' . shift()->{'name'
+} . ".\n"; };
}
1;
package main;
my $mya = My::A->new({name => 'Dave'});
$mya->greet();
You can bless a reference into any string you want. And in this case, you can assign a subroutine reference to any typeglob you want. In the example above I'm creating My::A::new, and My::A::greet. Yes, it's a little more work, but where there's work, there's a need for automation:
my %subs = (
new => sub { # constructor goes here... },
greet => sub { # Greeter goes here... },
);
while (my ($name, $code) = each %subs) {
no strict 'refs';
*{$pkg_sub . '::' . $name} = $code;
}
This hash based method has the advantage of releasing strict 'refs' in a much smaller scope. To be clear, you don't need a package My::A; statement to be able to create subroutines and methods in the My::A namespace; you just have to do without the conveniences package provides, crafting the subroutine namespaces manually.
And, in fact, this method is how Class:Builder works (snippet from Class::Builder):
{
# ...
no strict 'refs';
# ...
while (my ($name, $code) = each %methods){
*{"$class"."::"."$name"} = $code;
}
}
|